1 #include <stdio.h>
2 #include <string.h>
3 #include <linux/bpf.h>
4 #include <unistd.h>
5 #include <asm/unistd.h>
6 #include <net/if.h>
7 #include "l3lb.h"
8
sys_bpf(enum bpf_cmd cmd,union bpf_attr * attr,unsigned int size)9 static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size)
10 {
11 return syscall(__NR_bpf, cmd, attr, size);
12 }
13
ptr_to_u64(const void * ptr)14 static inline __u64 ptr_to_u64(const void *ptr)
15 {
16 return (__u64) (unsigned long) ptr;
17 }
18
parse_ipnetwork(char * p)19 unsigned int parse_ipnetwork(char *p) {
20 int k, i=0, b;
21 unsigned int ip=0, mk=0xffffffff;
22 for (k=0; k<4; k++) {
23 b=0;
24 if (p[i]<'0'||p[i]>'9') return 0;
25 while(p[i]>='0'&&p[i]<='9') {
26 b=b*10+p[i++]-'0';
27 if (b>256) return 0;
28 }
29 if (k<3&&p[i]!='.') return 0;
30 if (k==3&&p[i]!=0&&p[i]!='/') return 0;
31 ip = (ip<<8) | b;
32 if (k==3) break;
33 i++;
34 }
35 if (p[i]==0) mk=0xffffffff;
36 else if (p[i]=='/') {
37 i++; b=0;
38 while(p[i]>='0'&&p[i]<='9') {
39 b=b*10+p[i++]-'0';
40 if (b>32) return 0;
41 }
42 if (p[i]!=0||b>32||b<1) return 0;
43 b=32-b;
44 mk>>=b; mk<<=b;
45 } else return 0;
46 return ip&mk;
47 }
48
main(int argc,char * argv[])49 int main(int argc, char *argv[]) {
50 unsigned int ip;
51 BNode value;
52 union bpf_attr attr_pin, attr_elem;
53 int fd, rc;
54 memset(&attr_pin, 0, sizeof(attr_pin));
55 memset(&attr_elem, 0, sizeof(attr_elem));
56 attr_pin.pathname = ptr_to_u64("/sys/fs/bpf/l3bindings");
57 fd = sys_bpf(BPF_OBJ_GET, &attr_pin, sizeof(attr_pin));
58 if (fd<0) {
59 printf("bpf map /sys/fs/bpf/l3bindings not exist yet, need to start bpf prog first\n");
60 return 1;
61 }
62 attr_elem.map_fd = fd;
63 attr_elem.key = ptr_to_u64(&ip);
64 attr_elem.value = ptr_to_u64(&value);
65 if (argc != 6) {
66 printf("usage: %s [sip] [if_from] [ip_from] [if_to] [ip_to]\n", argv[0]);
67 return 1;
68 }
69 ip = parse_ipnetwork(argv[1]);
70 if (ip == 0) {
71 printf("ip network %s not valid\n", argv[1]);
72 return 1;
73 }
74 value.ifin = if_nametoindex(argv[2]);
75 if (!value.ifin) {
76 printf("interface %s not found\n", argv[2]);
77 return 1;
78 }
79 value.saddr = parse_ip(argv[3]);
80 if (value.saddr == 0) {
81 printf("source ip %s not valid\n", argv[3]);
82 return 1;
83 }
84 value.ifout = if_nametoindex(argv[4]);
85 if (!value.ifout) {
86 printf("interface %s not found\n", argv[4]);
87 return 1;
88 }
89 value.daddr = parse_ip(argv[5]);
90 if (value.daddr == 0) {
91 printf("target ip %s not valid\n", argv[5]);
92 return 1;
93 }
94 rc = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr_elem, sizeof(attr_elem));
95 if (rc<0) {
96 printf("fail to register the L3 binding rule\n");
97 return 1;
98 }
99 return 0;
100 }
101