X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Flibiproute%2Fiptunnel.c;h=3327b27a323d15d7458fccbc030cdc39ee2c344c;hb=7b72fc12000c878e11d5f0b245f83c0d71b29f58;hp=4524d49546b5ea3d8a20d54a83d85eb861539e5b;hpb=63fc1a9e08fabfc8ba96bad80731673ef40bf5cb;p=oweals%2Fbusybox.git diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c index 4524d4954..3327b27a3 100644 --- a/networking/libiproute/iptunnel.c +++ b/networking/libiproute/iptunnel.c @@ -14,39 +14,32 @@ * Phil Karn 990408: "pmtudisc" flag */ -#include "libbb.h" -#include -#include - -#include -#include - +//#include +//#include #include - #include #include - #include #ifndef __constant_htons #define __constant_htons htons #endif #include +#include "ip_common.h" /* #include "libbb.h" is inside */ #include "rt_names.h" #include "utils.h" -#include "ip_common.h" +/* Dies on error */ static int do_ioctl_get_ifindex(char *dev) { struct ifreq ifr; int fd; - strcpy(ifr.ifr_name, dev); - fd = socket(AF_INET, SOCK_DGRAM, 0); + strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); if (ioctl(fd, SIOCGIFINDEX, &ifr)) { - bb_perror_msg("ioctl"); - return 0; + bb_perror_msg_and_die("SIOCGIFINDEX"); } close(fd); return ifr.ifr_ifindex; @@ -57,94 +50,90 @@ static int do_ioctl_get_iftype(char *dev) struct ifreq ifr; int fd; - strcpy(ifr.ifr_name, dev); - fd = socket(AF_INET, SOCK_DGRAM, 0); + strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); if (ioctl(fd, SIOCGIFHWADDR, &ifr)) { - bb_perror_msg("ioctl"); + bb_perror_msg("SIOCGIFHWADDR"); return -1; } close(fd); return ifr.ifr_addr.sa_family; } - static char *do_ioctl_get_ifname(int idx) { - static struct ifreq ifr; + struct ifreq ifr; int fd; ifr.ifr_ifindex = idx; - fd = socket(AF_INET, SOCK_DGRAM, 0); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); if (ioctl(fd, SIOCGIFNAME, &ifr)) { - bb_perror_msg("ioctl"); + bb_perror_msg("SIOCGIFNAME"); return NULL; } close(fd); - return ifr.ifr_name; + return xstrndup(ifr.ifr_name, sizeof(ifr.ifr_name)); } - - -static int do_get_ioctl(char *basedev, struct ip_tunnel_parm *p) +static int do_get_ioctl(const char *basedev, struct ip_tunnel_parm *p) { struct ifreq ifr; int fd; int err; - strcpy(ifr.ifr_name, basedev); + strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name)); ifr.ifr_ifru.ifru_data = (void*)p; - fd = socket(AF_INET, SOCK_DGRAM, 0); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); err = ioctl(fd, SIOCGETTUNNEL, &ifr); if (err) { - bb_perror_msg("ioctl"); + bb_perror_msg("SIOCGETTUNNEL"); } close(fd); return err; } -static int do_add_ioctl(int cmd, char *basedev, struct ip_tunnel_parm *p) +/* Dies on error, otherwise returns 0 */ +static int do_add_ioctl(int cmd, const char *basedev, struct ip_tunnel_parm *p) { struct ifreq ifr; int fd; - int err; if (cmd == SIOCCHGTUNNEL && p->name[0]) { - strcpy(ifr.ifr_name, p->name); + strncpy(ifr.ifr_name, p->name, sizeof(ifr.ifr_name)); } else { - strcpy(ifr.ifr_name, basedev); + strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name)); } ifr.ifr_ifru.ifru_data = (void*)p; - fd = socket(AF_INET, SOCK_DGRAM, 0); - err = ioctl(fd, cmd, &ifr); - if (err) { - bb_perror_msg("ioctl"); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); + if (ioctl(fd, cmd, &ifr)) { + bb_perror_msg_and_die("ioctl"); } close(fd); - return err; + return 0; } -static int do_del_ioctl(char *basedev, struct ip_tunnel_parm *p) +/* Dies on error, otherwise returns 0 */ +static int do_del_ioctl(const char *basedev, struct ip_tunnel_parm *p) { struct ifreq ifr; int fd; - int err; if (p->name[0]) { - strcpy(ifr.ifr_name, p->name); + strncpy(ifr.ifr_name, p->name, sizeof(ifr.ifr_name)); } else { - strcpy(ifr.ifr_name, basedev); + strncpy(ifr.ifr_name, basedev, sizeof(ifr.ifr_name)); } ifr.ifr_ifru.ifru_data = (void*)p; - fd = socket(AF_INET, SOCK_DGRAM, 0); - err = ioctl(fd, SIOCDELTUNNEL, &ifr); - if (err) { - bb_perror_msg("ioctl"); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); + if (ioctl(fd, SIOCDELTUNNEL, &ifr)) { + bb_perror_msg_and_die("SIOCDELTUNNEL"); } close(fd); - return err; + return 0; } -static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) +/* Dies on error */ +static void parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; @@ -164,27 +153,23 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { - bb_error_msg("You managed to ask for more than one tunnel mode."); - exit(-1); + bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); } p->iph.protocol = IPPROTO_IPIP; } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { - bb_error_msg("You managed to ask for more than one tunnel mode."); - exit(-1); + bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); } p->iph.protocol = IPPROTO_GRE; } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { - bb_error_msg("You managed to ask for more than one tunnel mode."); - exit(-1); + bb_error_msg_and_die("you managed to ask for more than one tunnel mode"); } p->iph.protocol = IPPROTO_IPV6; } else { - bb_error_msg("Cannot guess tunnel mode."); - exit(-1); + bb_error_msg_and_die("cannot guess tunnel mode"); } } else if (strcmp(*argv, "key") == 0) { unsigned uval; @@ -195,8 +180,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->i_key = p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { - bb_error_msg("invalid value of \"key\""); - exit(-1); + bb_error_msg_and_die("invalid value of \"key\""); } p->i_key = p->o_key = htonl(uval); } @@ -208,8 +192,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { - bb_error_msg("invalid value of \"ikey\""); - exit(-1); + bb_error_msg_and_die("invalid value of \"ikey\""); } p->i_key = htonl(uval); } @@ -221,8 +204,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { - bb_error_msg("invalid value of \"okey\""); - exit(-1); + bb_error_msg_and_die("invalid value of \"okey\""); } p->o_key = htonl(uval); } @@ -267,7 +249,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) } } else if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { - __u32 uval; + uint32_t uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) @@ -286,15 +268,15 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (do_get_ioctl(*argv, &old_p)) - return -1; + exit(1); *p = old_p; } } count++; - argc--; argv++; + argc--; + argv++; } - if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; @@ -306,15 +288,12 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { - bb_error_msg("Keys are not allowed with ipip and sit."); - return -1; + bb_error_msg_and_die("keys are not allowed with ipip and sit"); } } if (medium[0]) { p->link = do_ioctl_get_ifindex(medium); - if (p->link == 0) - return -1; } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { @@ -326,23 +305,20 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { - bb_error_msg("Broadcast tunnel requires a source address."); - return -1; + bb_error_msg_and_die("broadcast tunnel requires a source address"); } - return 0; } +/* Return value becomes exitcode. It's okay to not return at all */ static int do_add(int cmd, int argc, char **argv) { struct ip_tunnel_parm p; - if (parse_args(argc, argv, cmd, &p) < 0) - return -1; + parse_args(argc, argv, cmd, &p); if (p.iph.ttl && p.iph.frag_off == 0) { - bb_error_msg("ttl != 0 and noptmudisc are incompatible"); - return -1; + bb_error_msg_and_die("ttl != 0 and noptmudisc are incompatible"); } switch (p.iph.protocol) { @@ -353,18 +329,16 @@ static int do_add(int cmd, int argc, char **argv) case IPPROTO_IPV6: return do_add_ioctl(cmd, "sit0", &p); default: - bb_error_msg("cannot determine tunnel mode (ipip, gre or sit)"); - return -1; + bb_error_msg_and_die("cannot determine tunnel mode (ipip, gre or sit)"); } - return -1; } +/* Return value becomes exitcode. It's okay to not return at all */ static int do_del(int argc, char **argv) { struct ip_tunnel_parm p; - if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0) - return -1; + parse_args(argc, argv, SIOCDELTUNNEL, &p); switch (p.iph.protocol) { case IPPROTO_IPIP: @@ -376,7 +350,6 @@ static int do_del(int argc, char **argv) default: return do_del_ioctl(p.name, &p); } - return -1; } static void print_tunnel(struct ip_tunnel_parm *p) @@ -399,8 +372,10 @@ static void print_tunnel(struct ip_tunnel_parm *p) p->iph.daddr ? s1 : "any", p->iph.saddr ? s2 : "any"); if (p->link) { char *n = do_ioctl_get_ifname(p->link); - if (n) + if (n) { printf(" dev %s ", n); + free(n); + } } if (p->iph.ttl) printf(" ttl %d ", p->iph.ttl); @@ -409,49 +384,48 @@ static void print_tunnel(struct ip_tunnel_parm *p) if (p->iph.tos) { SPRINT_BUF(b1); printf(" tos"); - if (p->iph.tos&1) + if (p->iph.tos & 1) printf(" inherit"); - if (p->iph.tos&~1) - printf("%c%s ", p->iph.tos&1 ? '/' : ' ', - rtnl_dsfield_n2a(p->iph.tos&~1, b1, sizeof(b1))); + if (p->iph.tos & ~1) + printf("%c%s ", p->iph.tos & 1 ? '/' : ' ', + rtnl_dsfield_n2a(p->iph.tos & ~1, b1, sizeof(b1))); } - if (!(p->iph.frag_off&htons(IP_DF))) + if (!(p->iph.frag_off & htons(IP_DF))) printf(" nopmtudisc"); - if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key) + if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key) printf(" key %s", s3); - else if ((p->i_flags|p->o_flags)&GRE_KEY) { - if (p->i_flags&GRE_KEY) + else if ((p->i_flags | p->o_flags) & GRE_KEY) { + if (p->i_flags & GRE_KEY) printf(" ikey %s ", s3); - if (p->o_flags&GRE_KEY) + if (p->o_flags & GRE_KEY) printf(" okey %s ", s4); } - if (p->i_flags&GRE_SEQ) - printf("%s Drop packets out of sequence.\n", _SL_); - if (p->i_flags&GRE_CSUM) - printf("%s Checksum in received packet is required.", _SL_); - if (p->o_flags&GRE_SEQ) - printf("%s Sequence packets on output.", _SL_); - if (p->o_flags&GRE_CSUM) - printf("%s Checksum output packets.", _SL_); + if (p->i_flags & GRE_SEQ) + printf("%c Drop packets out of sequence.\n", _SL_); + if (p->i_flags & GRE_CSUM) + printf("%c Checksum in received packet is required.", _SL_); + if (p->o_flags & GRE_SEQ) + printf("%c Sequence packets on output.", _SL_); + if (p->o_flags & GRE_CSUM) + printf("%c Checksum output packets.", _SL_); } -static int do_tunnels_list(struct ip_tunnel_parm *p) +static void do_tunnels_list(struct ip_tunnel_parm *p) { char name[IFNAMSIZ]; - unsigned long rx_bytes, rx_packets, rx_errs, rx_drops, - rx_fifo, rx_frame, - tx_bytes, tx_packets, tx_errs, tx_drops, - tx_fifo, tx_colls, tx_carrier, rx_multi; + unsigned long rx_bytes, rx_packets, rx_errs, rx_drops, + rx_fifo, rx_frame, + tx_bytes, tx_packets, tx_errs, tx_drops, + tx_fifo, tx_colls, tx_carrier, rx_multi; int type; struct ip_tunnel_parm p1; - char buf[512]; - FILE *fp = fopen("/proc/net/dev", "r"); + FILE *fp = fopen_or_warn("/proc/net/dev", "r"); + if (fp == NULL) { - perror("fopen"); - return -1; + return; } fgets(buf, sizeof(buf), fp); @@ -459,11 +433,13 @@ static int do_tunnels_list(struct ip_tunnel_parm *p) while (fgets(buf, sizeof(buf), fp) != NULL) { char *ptr; - buf[sizeof(buf) - 1] = 0; - if ((ptr = strchr(buf, ':')) == NULL || + + /*buf[sizeof(buf) - 1] = 0; - fgets is safe anyway */ + ptr = strchr(buf, ':'); + if (ptr == NULL || (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) { - bb_error_msg("Wrong format of /proc/net/dev. Sorry."); - return -1; + bb_error_msg("wrong format of /proc/net/dev. Sorry"); + return; } if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu", &rx_bytes, &rx_packets, &rx_errs, &rx_drops, @@ -475,7 +451,7 @@ static int do_tunnels_list(struct ip_tunnel_parm *p) continue; type = do_ioctl_get_iftype(name); if (type == -1) { - bb_error_msg("Failed to get type of [%s]", name); + bb_error_msg("cannot get type of [%s]", name); continue; } if (type != ARPHRD_TUNNEL && type != ARPHRD_IPGRE && type != ARPHRD_SIT) @@ -490,18 +466,17 @@ static int do_tunnels_list(struct ip_tunnel_parm *p) (p->i_key && p1.i_key != p->i_key)) continue; print_tunnel(&p1); - printf("\n"); + puts(""); } - return 0; } +/* Return value becomes exitcode. It's okay to not return at all */ static int do_show(int argc, char **argv) { int err; struct ip_tunnel_parm p; - if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0) - return -1; + parse_args(argc, argv, SIOCGETTUNNEL, &p); switch (p.iph.protocol) { case IPPROTO_IPIP: @@ -521,10 +496,11 @@ static int do_show(int argc, char **argv) return -1; print_tunnel(&p); - printf("\n"); + puts(""); return 0; } +/* Return value becomes exitcode. It's okay to not return at all */ int do_iptunnel(int argc, char **argv) { if (argc > 0) { @@ -541,6 +517,5 @@ int do_iptunnel(int argc, char **argv) } else return do_show(0, NULL); - bb_error_msg("Command \"%s\" is unknown.", *argv); - exit(-1); + bb_error_msg_and_die("command \"%s\" is unknown", *argv); }