2 * Lightweight Autonomic Network Architecture
4 * Functional block userspace configuration tool for LANA.
6 * strlcpy taken from the Linux kernel.
7 * Copyright 1991, 1992 Linus Torvalds <torvalds@linux-foundation.org>
9 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
10 * Swiss federal institute of technology (ETH Zurich)
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <linux/netlink.h>
25 #include <linux/types.h>
31 # define likely(x) __builtin_expect(!!(x), 1)
34 # define unlikely(x) __builtin_expect(!!(x), 0)
37 # define bug() __builtin_trap()
40 #define PROGNAME "fbctl"
41 #define VERSNAME "0.9"
43 size_t strlcpy(char *dest
, const char *src
, size_t size
)
45 size_t ret
= strlen(src
);
48 size_t len
= (ret
>= size
) ? size
- 1 : ret
;
49 memcpy(dest
, src
, len
);
56 static inline void die(void)
61 static inline void panic(char *msg
, ...)
65 vfprintf(stderr
, msg
, vl
);
71 static inline void whine(char *msg
, ...)
75 vfprintf(stderr
, msg
, vl
);
79 static void *xzmalloc(size_t size
)
83 if (unlikely(size
== 0))
84 panic("xzmalloc: zero size\n");
87 if (unlikely(ptr
== NULL
))
88 panic("xzmalloc: out of memory (allocating %lu bytes)\n",
95 static void xfree(void *ptr
)
97 if (unlikely(ptr
== NULL
))
98 panic("xfree: NULL pointer given as argument\n");
102 void check_for_root_maybe_die(void)
105 panic("Uhhuh, not root?! \n");
106 if (geteuid() != getuid())
107 panic("Uhhuh, not root?! \n");
110 static void usage(void)
112 printf("\n%s %s\n", PROGNAME
, VERSNAME
);
113 printf("Usage: %s <cmd> [<args> ...]\n", PROGNAME
);
114 printf("Commands:\n");
115 printf(" preload <module> - preload module\n");
116 printf(" add <name> <type> - add fblock instance\n");
117 printf(" set <name> <key=val> - set option for fblock\n");
118 printf(" rm <name> - remove fblock from stack if unbound\n");
119 printf(" bind <name1> <name2> - bind two fblocks\n");
120 printf(" unbind <name1> <name2> - unbind two fblocks\n");
121 printf(" xchg <name1> <name2> - exchange fb1 with fb2\n");
122 printf(" note: name1 and name2 then \n");
123 printf(" point to the same fblock\n");
124 printf(" subscribe <name1> <name2> - subscribe fb2 to fb1 to rcv events\n");
125 printf(" unsubscribe <name1> <name2> - unsubscribe fb2 from fb1\n");
127 printf("Please report bugs to <dborkma@tik.ee.ethz.ch>\n");
128 printf("Copyright (C) 2011 Daniel Borkmann\n");
129 printf("License: GNU GPL version 2\n");
130 printf("This is free software: you are free to change and redistribute it.\n");
131 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
136 static void version(void)
138 printf("\n%s %s\n", PROGNAME
, VERSNAME
);
139 printf("Please report bugs to <dborkma@tik.ee.ethz.ch>\n");
140 printf("Copyright (C) 2011 Daniel Borkmann\n");
141 printf("License: GNU GPL version 2\n");
142 printf("This is free software: you are free to change and redistribute it.\n");
143 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
148 static void do_preload(int argc
, char **argv
)
151 char path
[256], file
[320], cmd
[512], *env
;
155 panic("Invalid args!\n");
157 memset(cmd
, 0, sizeof(cmd
));
158 env
= getenv("FBCFG_PRELOAD_DIR");
160 snprintf(cmd
, sizeof(cmd
), "modprobe %s", argv
[0]);
161 cmd
[sizeof(cmd
) - 1] = 0;
163 ret
= WEXITSTATUS(ret
);
165 panic("Preload failed!\n");
169 memset(path
, 0, sizeof(path
));
170 memcpy(path
, env
, sizeof(path
));
171 path
[sizeof(path
) - 1] = 0;
172 memset(file
, 0, sizeof(file
));
173 snprintf(file
, sizeof(file
), "%s%s.ko", path
, argv
[0]);
174 file
[sizeof(file
) - 1] = 0;
176 fd
= open(file
, O_RDONLY
);
178 panic("Module does not exist!\n");
179 ret
= fstat(fd
, &sb
);
181 panic("Cannot fstat file!\n");
182 if (!S_ISREG (sb
.st_mode
))
183 panic("Module is not a regular file!\n");
184 if (sb
.st_uid
!= geteuid())
185 panic("Module is not owned by root! Someone could "
186 "compromise your system!\n");
189 snprintf(cmd
, sizeof(cmd
), "insmod %s", file
);
190 cmd
[sizeof(cmd
) - 1] = 0;
192 ret
= WEXITSTATUS(ret
);
194 panic("Preload failed!\n");
197 static void send_netlink(struct lananlmsg
*lmsg
)
200 struct sockaddr_nl src_addr
, dest_addr
;
201 struct nlmsghdr
*nlh
;
208 sock
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_USERCTL
);
209 if (unlikely(sock
< 0))
210 panic("Cannot get NETLINK_USERCTL socket from kernel! "
211 "Modules not loaded?!\n");
213 memset(&src_addr
, 0, sizeof(src_addr
));
214 src_addr
.nl_family
= AF_NETLINK
;
216 src_addr
.nl_pid
= getpid();
217 src_addr
.nl_groups
= 0;
219 ret
= bind(sock
, (struct sockaddr
*) &src_addr
, sizeof(src_addr
));
221 panic("Cannot bind socket!\n");
223 memset(&dest_addr
, 0, sizeof(dest_addr
));
224 dest_addr
.nl_family
= AF_NETLINK
;
225 dest_addr
.nl_pad
= 0;
226 dest_addr
.nl_pid
= 0;
227 dest_addr
.nl_groups
= 0;
229 nlh
= xzmalloc(NLMSG_SPACE(sizeof(*lmsg
)));
230 nlh
->nlmsg_len
= NLMSG_SPACE(sizeof(*lmsg
));
231 nlh
->nlmsg_pid
= getpid();
232 nlh
->nlmsg_type
= USERCTLGRP_CONF
;
233 nlh
->nlmsg_flags
= NLM_F_REQUEST
;
235 memcpy(NLMSG_DATA(nlh
), lmsg
, sizeof(*lmsg
));
238 iov
.iov_len
= nlh
->nlmsg_len
;
240 memset(&msg
, 0, sizeof(msg
));
241 msg
.msg_name
= &dest_addr
;
242 msg
.msg_namelen
= sizeof(dest_addr
);
246 ret
= sendmsg(sock
, &msg
, 0);
247 if (unlikely(ret
< 0))
248 panic("Cannot send NETLINK message to the kernel!\n");
254 static void do_add(int argc
, char **argv
)
256 struct lananlmsg lmsg
;
257 struct lananlmsg_add
*msg
;
262 memset(&lmsg
, 0, sizeof(lmsg
));
263 lmsg
.cmd
= NETLINK_USERCTL_CMD_ADD
;
264 msg
= (struct lananlmsg_add
*) lmsg
.buff
;
265 strlcpy(msg
->name
, argv
[0], sizeof(msg
->name
));
266 strlcpy(msg
->type
, argv
[1], sizeof(msg
->type
));
270 static void do_set(int argc
, char **argv
)
272 struct lananlmsg lmsg
;
273 struct lananlmsg_set
*msg
;
278 memset(&lmsg
, 0, sizeof(lmsg
));
279 lmsg
.cmd
= NETLINK_USERCTL_CMD_SET
;
280 msg
= (struct lananlmsg_set
*) lmsg
.buff
;
281 strlcpy(msg
->name
, argv
[0], sizeof(msg
->name
));
282 strlcpy(msg
->option
, argv
[1], sizeof(msg
->option
));
286 static void do_rm(int argc
, char **argv
)
288 struct lananlmsg lmsg
;
289 struct lananlmsg_rm
*msg
;
294 memset(&lmsg
, 0, sizeof(lmsg
));
295 lmsg
.cmd
= NETLINK_USERCTL_CMD_RM
;
296 msg
= (struct lananlmsg_rm
*) lmsg
.buff
;
297 strlcpy(msg
->name
, argv
[0], sizeof(msg
->name
));
301 static void do_bind(int argc
, char **argv
)
303 struct lananlmsg lmsg
;
304 struct lananlmsg_bind
*msg
;
309 memset(&lmsg
, 0, sizeof(lmsg
));
310 lmsg
.cmd
= NETLINK_USERCTL_CMD_BIND
;
311 msg
= (struct lananlmsg_bind
*) lmsg
.buff
;
312 strlcpy(msg
->name1
, argv
[0], sizeof(msg
->name1
));
313 strlcpy(msg
->name2
, argv
[1], sizeof(msg
->name2
));
317 static void do_unbind(int argc
, char **argv
)
319 struct lananlmsg lmsg
;
320 struct lananlmsg_unbind
*msg
;
325 memset(&lmsg
, 0, sizeof(lmsg
));
326 lmsg
.cmd
= NETLINK_USERCTL_CMD_UNBIND
;
327 msg
= (struct lananlmsg_unbind
*) lmsg
.buff
;
328 strlcpy(msg
->name1
, argv
[0], sizeof(msg
->name1
));
329 strlcpy(msg
->name2
, argv
[1], sizeof(msg
->name2
));
333 int main(int argc
, char **argv
)
335 check_for_root_maybe_die();
340 if (!strncmp("help", argv
[0], strlen("help")))
342 else if (!strncmp("version", argv
[0], strlen("version")))
344 else if (!strncmp("preload", argv
[0], strlen("preload")))
345 do_preload(--argc
, ++argv
);
346 else if (!strncmp("add", argv
[0], strlen("add")))
347 do_add(--argc
, ++argv
);
348 else if (!strncmp("set", argv
[0], strlen("set")))
349 do_set(--argc
, ++argv
);
350 else if (!strncmp("rm", argv
[0], strlen("rm")))
351 do_rm(--argc
, ++argv
);
352 else if (!strncmp("bind", argv
[0], strlen("bind")))
353 do_bind(--argc
, ++argv
);
354 else if (!strncmp("unbind", argv
[0], strlen("unbind")))
355 do_unbind(--argc
, ++argv
);