1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)ifconfig.c 4.12 (Berkeley) 06/06/85"; 15 #endif not lint 16 17 18 #include <sys/types.h> 19 #include <sys/socket.h> 20 #include <sys/ioctl.h> 21 22 #include <net/if.h> 23 #include <netinet/in.h> 24 25 #define NSIP 26 #include <netns/ns.h> 27 #include <netns/ns_if.h> 28 29 #include <stdio.h> 30 #include <errno.h> 31 #include <ctype.h> 32 #include <netdb.h> 33 34 extern int errno; 35 struct ifreq ifr; 36 struct sockaddr_in sin = { AF_INET }; 37 struct sockaddr_in broadaddr; 38 struct sockaddr_in netmask = { AF_INET }; 39 struct sockaddr_in ipdst = { AF_INET }; 40 char name[30]; 41 int flags; 42 int setaddr; 43 int setmask; 44 int setbroadaddr; 45 int setipdst; 46 int s; 47 extern int errno; 48 49 int setifflags(), setifaddr(), setifdstaddr(), setifnetmask(); 50 int setifbroadaddr(), setifipdst(); 51 52 #define NEXTARG 0xffffff 53 54 struct cmd { 55 char *c_name; 56 int c_parameter; /* NEXTARG means next argv */ 57 int (*c_func)(); 58 } cmds[] = { 59 { "up", IFF_UP, setifflags } , 60 { "down", -IFF_UP, setifflags }, 61 { "trailers", -IFF_NOTRAILERS,setifflags }, 62 { "-trailers", IFF_NOTRAILERS, setifflags }, 63 { "arp", -IFF_NOARP, setifflags }, 64 { "-arp", IFF_NOARP, setifflags }, 65 #ifdef IFF_LOCAL 66 { "local", IFF_LOCAL, setifflags }, 67 { "-local", -IFF_LOCAL, setifflags }, 68 #endif 69 { "debug", IFF_DEBUG, setifflags }, 70 { "-debug", -IFF_DEBUG, setifflags }, 71 #ifdef notdef 72 #define EN_SWABIPS 0x1000 73 { "swabips", EN_SWABIPS, setifflags }, 74 { "-swabips", -EN_SWABIPS, setifflags }, 75 #endif 76 { "netmask", NEXTARG, setifnetmask }, 77 { "broadcast", NEXTARG, setifbroadaddr }, 78 { "ipdst", NEXTARG, setifipdst }, 79 { 0, 0, setifaddr }, 80 { 0, 0, setifdstaddr }, 81 }; 82 83 /* 84 * XNS support liberally adapted from 85 * code written at the University of Maryland 86 * principally by James O'Toole and Chris Torek. 87 */ 88 89 int in_status(), in_getaddr(); 90 int xns_status(), xns_getaddr(); 91 92 /* Known address families */ 93 struct afswtch { 94 char *af_name; 95 short af_af; 96 int (*af_status)(); 97 int (*af_getaddr)(); 98 } afs[] = { 99 { "inet", AF_INET, in_status, in_getaddr }, 100 { "ns", AF_NS, xns_status, xns_getaddr }, 101 { 0, 0, 0, 0 } 102 }; 103 104 struct afswtch *afp; /*the address family being set or asked about*/ 105 106 main(argc, argv) 107 int argc; 108 char *argv[]; 109 { 110 int af = AF_INET; 111 if (argc < 2) { 112 fprintf(stderr, "usage: ifconfig interface [ af %s %s %s %s\n", 113 "[ address [ dest_addr ] ] [ up ] [ down ]", 114 "[ netmask mask ] ]", 115 "[ trailers | -trailers ]", 116 "[ arp | -arp ] ]"); 117 exit(1); 118 } 119 argc--, argv++; 120 strncpy(name, *argv, sizeof(name - 1)); 121 name[sizeof name - 1] = 0; 122 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 123 argc--, argv++; 124 if (argc > 0) { 125 struct afswtch *myafp; 126 127 for (myafp = afp = afs; myafp->af_name; myafp++) 128 if (strcmp(myafp->af_name, *argv) == 0) { 129 afp = myafp; argc--; argv++; 130 break; 131 } 132 af = ifr.ifr_addr.sa_family = afp->af_af; 133 } 134 s = socket(af, SOCK_DGRAM, 0); 135 if (s < 0) { 136 perror("ifconfig: socket"); 137 exit(1); 138 } 139 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 140 Perror("ioctl (SIOCGIFFLAGS)"); 141 exit(1); 142 } 143 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 144 flags = ifr.ifr_flags; 145 if (af == AF_INET) { 146 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 147 if (errno != EADDRNOTAVAIL) 148 Perror("ioctl (SIOCGIFNETMASK)"); 149 } else 150 netmask.sin_addr = 151 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 152 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 153 } 154 if (argc == 0) { 155 status(); 156 exit(0); 157 } 158 while (argc > 0) { 159 register struct cmd *p; 160 161 for (p = cmds; p->c_name; p++) 162 if (strcmp(*argv, p->c_name) == 0) 163 break; 164 if (p->c_name == 0 && setaddr) 165 p++; /* got src, do dst */ 166 if (p->c_func) { 167 if (p->c_parameter == NEXTARG) { 168 (*p->c_func)(argv[1]); 169 argc--, argv++; 170 } else 171 (*p->c_func)(*argv, p->c_parameter); 172 } 173 argc--, argv++; 174 } 175 if ((setmask || setaddr) && (af == AF_INET)){ 176 /* 177 * If setting the address and not the mask, 178 * clear any existing mask and the kernel will then 179 * assign the default. If setting both, 180 * set the mask first, so the address will be 181 * interpreted correctly. 182 */ 183 ifr.ifr_addr = *(struct sockaddr *)&netmask; 184 if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) 185 Perror("ioctl (SIOCSIFNETMASK)"); 186 } 187 if (setipdst && af==AF_NS) { 188 struct nsip_req rq; 189 int size = sizeof(rq); 190 191 rq.rq_ns = *(struct sockaddr *) &sin; 192 rq.rq_ip = *(struct sockaddr *) &ipdst; 193 194 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 195 Perror("Encapsulation Routing"); 196 setaddr = 0; 197 } 198 if (setaddr) { 199 ifr.ifr_addr = *(struct sockaddr *) &sin; 200 if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) 201 Perror("ioctl (SIOCSIFADDR)"); 202 } 203 if (setbroadaddr) { 204 ifr.ifr_addr = *(struct sockaddr *)&broadaddr; 205 if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0) 206 Perror("ioctl (SIOCSIFBRDADDR)"); 207 } 208 exit(0); 209 } 210 211 /*ARGSUSED*/ 212 setifaddr(addr, param) 213 char *addr; 214 short param; 215 { 216 /* 217 * Delay the ioctl to set the interface addr until flags are all set. 218 * The address interpretation may depend on the flags, 219 * and the flags may change when the address is set. 220 */ 221 setaddr++; 222 (*afp->af_getaddr)(addr, &sin); 223 } 224 225 setifnetmask(addr) 226 char *addr; 227 { 228 in_getaddr(addr, &netmask); 229 setmask++; 230 } 231 232 setifbroadaddr(addr) 233 char *addr; 234 { 235 (*afp->af_getaddr)(addr, &broadaddr); 236 setbroadaddr++; 237 } 238 239 setifipdst(addr) 240 char *addr; 241 { 242 in_getaddr(addr, &ipdst); 243 setipdst++; 244 } 245 246 /*ARGSUSED*/ 247 setifdstaddr(addr, param) 248 char *addr; 249 int param; 250 { 251 252 (*afp->af_getaddr)(addr, &ifr.ifr_addr); 253 if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) 254 Perror("ioctl (SIOCSIFDSTADDR)"); 255 } 256 257 setifflags(vname, value) 258 char *vname; 259 short value; 260 { 261 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 262 Perror("ioctl (SIOCGIFFLAGS)"); 263 exit(1); 264 } 265 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 266 flags = ifr.ifr_flags; 267 268 if (value < 0) { 269 value = -value; 270 flags &= ~value; 271 } else 272 flags |= value; 273 ifr.ifr_flags = flags; 274 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 275 Perror(vname); 276 } 277 278 /* 279 * Print the status of the interface. If an address family was 280 * specified, show it and it only; otherwise, show them all. 281 */ 282 status() 283 { 284 register struct afswtch *p = afp; 285 short af = ifr.ifr_addr.sa_family; 286 287 if ((p = afp) != NULL) { 288 (*p->af_status)(); 289 return; 290 } 291 for (p = afs; p->af_name; p++) { 292 ifr.ifr_addr.sa_family = p->af_af; 293 (*p->af_status)(); 294 } 295 } 296 297 #define IFFBITS \ 298 "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 299 \11LOCAL" 300 301 in_status() 302 { 303 struct sockaddr_in *sin; 304 char *inet_ntoa(); 305 306 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 307 if (errno == EADDRNOTAVAIL) 308 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 309 else 310 Perror("ioctl (SIOCGIFADDR)"); 311 } 312 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 313 sin = (struct sockaddr_in *)&ifr.ifr_addr; 314 printf("%s: %s ", name, inet_ntoa(sin->sin_addr)); 315 if (flags & IFF_POINTOPOINT) { 316 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 317 if (errno == EADDRNOTAVAIL) 318 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 319 else 320 Perror("ioctl (SIOCGIFDSTADDR)"); 321 } 322 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 323 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 324 printf("--> %s ", inet_ntoa(sin->sin_addr)); 325 } 326 printf("netmask %x ", ntohl(netmask.sin_addr.s_addr)); 327 printb("flags", flags, IFFBITS); putchar('\n'); 328 if (flags & IFF_BROADCAST) { 329 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 330 if (errno == EADDRNOTAVAIL) 331 return; 332 Perror("ioctl (SIOCGIFADDR)"); 333 } 334 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 335 sin = (struct sockaddr_in *)&ifr.ifr_addr; 336 printf("broadcast: %s\n", inet_ntoa(sin->sin_addr)); 337 } 338 } 339 340 341 xns_status() 342 { 343 struct sockaddr_ns *sns; 344 char *xns_ntoa(); 345 346 close(s); 347 s = socket(AF_NS, SOCK_DGRAM, 0); 348 if (s < 0) { 349 perror("ifconfig: socket"); 350 exit(1); 351 } 352 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 353 if (errno == EAFNOSUPPORT) 354 return; 355 Perror("ioctl (SIOCGIFADDR)"); 356 } 357 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 358 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 359 printf("%s: xns %s ", name, xns_ntoa(sns)); 360 printb("flags", flags, IFFBITS); 361 putchar('\n'); 362 } 363 364 Perror(cmd) 365 char *cmd; 366 { 367 extern int errno; 368 369 fprintf(stderr, "ifconfig: "); 370 switch (errno) { 371 372 case ENXIO: 373 fprintf(stderr, "%s: no such interface\n", cmd); 374 break; 375 376 case EPERM: 377 fprintf(stderr, "%s: permission denied\n", cmd); 378 break; 379 380 default: 381 perror(cmd); 382 } 383 exit(1); 384 } 385 386 struct in_addr inet_makeaddr(); 387 388 in_getaddr(s, saddr) 389 char *s; 390 struct sockaddr *saddr; 391 { 392 register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 393 struct hostent *hp; 394 struct netent *np; 395 int val; 396 397 sin->sin_family = AF_INET; 398 val = inet_addr(s); 399 if (val != -1) { 400 sin->sin_addr.s_addr = val; 401 return; 402 } 403 hp = gethostbyname(s); 404 if (hp) { 405 sin->sin_family = hp->h_addrtype; 406 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 407 return; 408 } 409 np = getnetbyname(s); 410 if (np) { 411 sin->sin_family = np->n_addrtype; 412 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 413 return; 414 } 415 fprintf(stderr, "%s: bad value\n", s); 416 exit(1); 417 } 418 419 /* 420 * Print a value a la the %b format of the kernel's printf 421 */ 422 printb(s, v, bits) 423 char *s; 424 register char *bits; 425 register unsigned short v; 426 { 427 register int i, any = 0; 428 register char c; 429 430 if (bits && *bits == 8) 431 printf("%s=%o", s, v); 432 else 433 printf("%s=%x", s, v); 434 bits++; 435 if (bits) { 436 putchar('<'); 437 while (i = *bits++) { 438 if (v & (1 << (i-1))) { 439 if (any) 440 putchar(','); 441 any = 1; 442 for (; (c = *bits) > 32; bits++) 443 putchar(c); 444 } else 445 for (; *bits > 32; bits++) 446 ; 447 } 448 putchar('>'); 449 } 450 } 451 452 #define setxnnet(a,b) {a = * (union ns_net *) &(b);} 453 454 xns_getaddr(addr, saddr) 455 char *addr; 456 struct sockaddr *saddr; 457 { 458 register struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr; 459 u_long netnum; 460 char *index(); 461 register char *s = index(addr, ':'); 462 register int i; 463 464 if (s!=NULL) *s = 0; 465 netnum = atoi(addr); 466 netnum = htonl(netnum); 467 setxnnet(sns->sns_addr.x_net, netnum); 468 sns->sns_family = AF_NS; 469 470 for (i = 0; i < 6; i++) { 471 if (s == NULL || *++s == 0) 472 break; 473 sns->sns_addr.x_host.c_host[i] = xtoi(s); 474 s = index(s, '.'); 475 } 476 477 } 478 479 char * 480 xns_ntoa(sns) 481 register struct sockaddr_ns *sns; 482 { 483 static char buf[30]; 484 485 sprintf (buf, "%d:%x.%x.%x.%x.%x.%x", 486 ntohl(ns_netof(sns->sns_addr)), 487 sns->sns_addr.x_host.c_host[0], sns->sns_addr.x_host.c_host[1], 488 sns->sns_addr.x_host.c_host[2], sns->sns_addr.x_host.c_host[3], 489 sns->sns_addr.x_host.c_host[4], sns->sns_addr.x_host.c_host[5]); 490 return (buf); 491 } 492 493 int xtoi(s) 494 register char *s; 495 { 496 register int res = 0, delta; 497 register char *cp; 498 static char base[] = "0123456789ABCDEFabcdef"; 499 500 for(; *s; s++) { 501 cp = index(base, *s); 502 if (cp==NULL) 503 break; 504 if ((delta = cp - base) > 15) 505 delta -= 6; 506 res = (res << 4) + delta; 507 } 508 return(res); 509 } 510