ip.c revision ede723964a065992bf9d0dbe3f780e65ca917872
1/* 2 * ip.c "ip" utility frontend. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10 * 11 * 12 * Changes: 13 * 14 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <syslog.h> 21#include <fcntl.h> 22#include <sys/socket.h> 23#include <netinet/in.h> 24#include <string.h> 25#include <errno.h> 26 27#include "SNAPSHOT.h" 28#include "utils.h" 29#include "ip_common.h" 30 31int preferred_family = AF_UNSPEC; 32int show_stats = 0; 33int resolve_hosts = 0; 34int oneline = 0; 35int timestamp = 0; 36char * _SL_ = NULL; 37char *batch_file = NULL; 38int force = 0; 39struct rtnl_handle rth; 40 41static void usage(void) __attribute__((noreturn)); 42 43static void usage(void) 44{ 45 fprintf(stderr, 46"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" 47" ip [ -force ] [-batch filename\n" 48"where OBJECT := { link | addr | route | rule | neigh | tunnel |\n" 49" maddr | mroute | monitor | xfrm }\n" 50" OPTIONS := { -V[ersion] | -s[tatistics] | -r[esolve] |\n" 51" -f[amily] { inet | inet6 | ipx | dnet | link } |\n" 52" -o[neline] | -t[imestamp] }\n"); 53 exit(-1); 54} 55 56static int do_help(int argc, char **argv) 57{ 58 usage(); 59} 60 61static const struct cmd { 62 const char *cmd; 63 int (*func)(int argc, char **argv); 64} cmds[] = { 65 { "address", do_ipaddr }, 66 { "maddress", do_multiaddr }, 67 { "route", do_iproute }, 68 { "rule", do_iprule }, 69 { "neighbor", do_ipneigh }, 70 { "neighbour", do_ipneigh }, 71 { "link", do_iplink }, 72 { "tunnel", do_iptunnel }, 73 { "tunl", do_iptunnel }, 74 { "monitor", do_ipmonitor }, 75 { "xfrm", do_xfrm }, 76 { "mroute", do_multiroute }, 77 { "help", do_help }, 78 { 0 } 79}; 80 81static int do_cmd(const char *argv0, int argc, char **argv) 82{ 83 const struct cmd *c, *m = NULL; 84 85 for (c = cmds; c->cmd; ++c) { 86 if (matches(argv0, c->cmd) == 0) { 87 if (m && m->func != c->func) { 88 fprintf(stderr, 89 "Ambiguious command \"%s\" matches both %s and %s\n", 90 argv0, m->cmd, c->cmd); 91 return -1; 92 } 93 m = c; 94 } 95 } 96 97 if (m) 98 return m->func(argc-1, argv+1); 99 100 fprintf(stderr, "Object \"%s\" is unknown, try \"ip help\".\n", argv0); 101 return -1; 102} 103 104static int batch(const char *name) 105{ 106 char *line = NULL; 107 size_t len = 0; 108 int ret = 0; 109 int lineno = 0; 110 111 if (name && strcmp(name, "-") != 0) { 112 if (freopen(name, "r", stdin) == NULL) { 113 fprintf(stderr, "Cannot open file \"%s\" for reading: %s=n", 114 name, strerror(errno)); 115 return -1; 116 } 117 } 118 119 if (rtnl_open(&rth, 0) < 0) { 120 fprintf(stderr, "Cannot open rtnetlink\n"); 121 return -1; 122 } 123 124 while (getcmdline(&line, &len, stdin) != -1) { 125 char *largv[100]; 126 int largc; 127 128 largc = makeargs(line, largv, 100); 129 if (largc == 0) 130 continue; /* blank line */ 131 132 if (do_cmd(largv[0], largc, largv)) { 133 fprintf(stderr, "Command failed %s:%d\n", name, lineno); 134 ret = 1; 135 if (!force) 136 break; 137 } 138 } 139 if (line) 140 free(line); 141 142 rtnl_close(&rth); 143 return ret; 144} 145 146 147int main(int argc, char **argv) 148{ 149 char *basename; 150 151 basename = strrchr(argv[0], '/'); 152 if (basename == NULL) 153 basename = argv[0]; 154 else 155 basename++; 156 157 while (argc > 1) { 158 char *opt = argv[1]; 159 if (strcmp(opt,"--") == 0) { 160 argc--; argv++; 161 break; 162 } 163 if (opt[0] != '-') 164 break; 165 if (opt[1] == '-') 166 opt++; 167 if (matches(opt, "-family") == 0) { 168 argc--; 169 argv++; 170 if (argc <= 1) 171 usage(); 172 if (strcmp(argv[1], "inet") == 0) 173 preferred_family = AF_INET; 174 else if (strcmp(argv[1], "inet6") == 0) 175 preferred_family = AF_INET6; 176 else if (strcmp(argv[1], "dnet") == 0) 177 preferred_family = AF_DECnet; 178 else if (strcmp(argv[1], "link") == 0) 179 preferred_family = AF_PACKET; 180 else if (strcmp(argv[1], "ipx") == 0) 181 preferred_family = AF_IPX; 182 else if (strcmp(argv[1], "help") == 0) 183 usage(); 184 else 185 invarg(argv[1], "invalid protocol family"); 186 } else if (strcmp(opt, "-4") == 0) { 187 preferred_family = AF_INET; 188 } else if (strcmp(opt, "-6") == 0) { 189 preferred_family = AF_INET6; 190 } else if (strcmp(opt, "-0") == 0) { 191 preferred_family = AF_PACKET; 192 } else if (strcmp(opt, "-I") == 0) { 193 preferred_family = AF_IPX; 194 } else if (strcmp(opt, "-D") == 0) { 195 preferred_family = AF_DECnet; 196 } else if (matches(opt, "-stats") == 0 || 197 matches(opt, "-statistics") == 0) { 198 ++show_stats; 199 } else if (matches(opt, "-resolve") == 0) { 200 ++resolve_hosts; 201 } else if (matches(opt, "-oneline") == 0) { 202 ++oneline; 203 } else if (matches(opt, "-timestamp") == 0) { 204 ++timestamp; 205#if 0 206 } else if (matches(opt, "-numeric") == 0) { 207 rtnl_names_numeric++; 208#endif 209 } else if (matches(opt, "-Version") == 0) { 210 printf("ip utility, iproute2-ss%s\n", SNAPSHOT); 211 exit(0); 212 } else if (matches(opt, "-force") == 0) { 213 ++force; 214 } else if (matches(opt, "-batch") == 0) { 215 argc--; 216 argv++; 217 if (argc <= 1) 218 usage(); 219 batch_file = argv[1]; 220 } else if (matches(opt, "-help") == 0) { 221 usage(); 222 } else { 223 fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt); 224 exit(-1); 225 } 226 argc--; argv++; 227 } 228 229 _SL_ = oneline ? "\\" : "\n" ; 230 231 if (batch_file) 232 return batch(batch_file); 233 234 if (rtnl_open(&rth, 0) < 0) 235 exit(1); 236 237 if (strlen(basename) > 2) 238 return do_cmd(basename+2, argc, argv); 239 240 if (argc > 1) 241 return do_cmd(argv[1], argc-1, argv+1); 242 243 rtnl_close(&rth); 244 usage(); 245} 246