natm.c revision 118824
1118824Sharti/* 2118824Sharti * Copyright (c) 2003 3118824Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4118824Sharti * All rights reserved. 5118824Sharti * 6118824Sharti * Redistribution and use in source and binary forms, with or without 7118824Sharti * modification, are permitted provided that the following conditions 8118824Sharti * are met: 9118824Sharti * 1. Redistributions of source code must retain the above copyright 10118824Sharti * notice, this list of conditions and the following disclaimer. 11118824Sharti * 2. Redistributions in binary form must reproduce the above copyright 12118824Sharti * notice, this list of conditions and the following disclaimer in the 13118824Sharti * documentation and/or other materials provided with the distribution. 14118824Sharti * 15118824Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16118824Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17118824Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18118824Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19118824Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20118824Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21118824Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22118824Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23118824Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24118824Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25118824Sharti * SUCH DAMAGE. 26118824Sharti * 27118824Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28118824Sharti */ 29118824Sharti#include <sys/cdefs.h> 30118824Sharti__FBSDID("$FreeBSD: head/sbin/atm/atmconfig/natm.c 118824 2003-08-12 14:25:57Z harti $"); 31118824Sharti 32118824Sharti#include <sys/types.h> 33118824Sharti#include <sys/socket.h> 34118824Sharti#include <sys/sysctl.h> 35118824Sharti#include <net/if.h> 36118824Sharti#include <net/if_var.h> 37118824Sharti#include <net/if_mib.h> 38118824Sharti#include <net/if_atm.h> 39118824Sharti#include <net/if_dl.h> 40118824Sharti#include <net/route.h> 41118824Sharti#include <netinet/in.h> 42118824Sharti#include <arpa/inet.h> 43118824Sharti#include <netdb.h> 44118824Sharti#include "atmconfig.h" 45118824Sharti#include "private.h" 46118824Sharti#include "diag.h" 47118824Sharti 48118824Shartistatic void natm_add(int, char *[]); 49118824Shartistatic void natm_delete(int, char *[]); 50118824Shartistatic void natm_show(int, char *[]); 51118824Sharti 52118824Sharticonst struct cmdtab natm_tab[] = { 53118824Sharti { "add", NULL, natm_add }, 54118824Sharti { "delete", NULL, natm_delete }, 55118824Sharti { "show", NULL, natm_show }, 56118824Sharti { NULL, NULL, NULL } 57118824Sharti}; 58118824Sharti 59118824Sharti/* 60118824Sharti * Structure to hold a route 61118824Sharti */ 62118824Shartistruct natm_route { 63118824Sharti TAILQ_ENTRY(natm_route) link; 64118824Sharti struct in_addr host; 65118824Sharti struct diagif *aif; 66118824Sharti u_int flags; 67118824Sharti int llcsnap; 68118824Sharti u_int vpi, vci; 69118824Sharti u_int traffic; 70118824Sharti u_int pcr, scr, mbs, icr, mcr; 71118824Sharti u_int tbe, nrm, trm, adtf, rif, rdf, cdf; 72118824Sharti}; 73118824Shartistatic TAILQ_HEAD(, natm_route) natm_route_list = 74118824Sharti TAILQ_HEAD_INITIALIZER(natm_route_list); 75118824Sharti 76118824Shartistatic void 77118824Shartistore_route(struct rt_msghdr *rtm) 78118824Sharti{ 79118824Sharti u_int i; 80118824Sharti struct natm_route *r; 81118824Sharti char *cp; 82118824Sharti struct sockaddr *sa; 83118824Sharti struct sockaddr_in *sain; 84118824Sharti struct sockaddr_dl *sdl; 85118824Sharti struct diagif *aif; 86118824Sharti u_int n; 87118824Sharti 88118824Sharti r = malloc(sizeof(*r)); 89118824Sharti if (r == NULL) 90118824Sharti err(1, "allocate route"); 91118824Sharti 92118824Sharti r->flags = rtm->rtm_flags; 93118824Sharti cp = (char *)(rtm + 1); 94118824Sharti for (i = 1; i != 0; i <<= 1) { 95118824Sharti if (rtm->rtm_addrs & i) { 96118824Sharti sa = (struct sockaddr *)cp; 97118824Sharti cp += roundup(sa->sa_len, sizeof(long)); 98118824Sharti switch (i) { 99118824Sharti 100118824Sharti case RTA_DST: 101118824Sharti if (sa->sa_family != AF_INET) { 102118824Sharti warnx("RTA_DST not AF_INET %u", sa->sa_family); 103118824Sharti goto fail; 104118824Sharti } 105118824Sharti sain = (struct sockaddr_in *)(void *)sa; 106118824Sharti if (sain->sin_len < 4) 107118824Sharti r->host.s_addr = INADDR_ANY; 108118824Sharti else 109118824Sharti r->host = sain->sin_addr; 110118824Sharti break; 111118824Sharti 112118824Sharti case RTA_GATEWAY: 113118824Sharti if (sa->sa_family != AF_LINK) { 114118824Sharti warnx("RTA_GATEWAY not AF_LINK"); 115118824Sharti goto fail; 116118824Sharti } 117118824Sharti sdl = (struct sockaddr_dl *)(void *)sa; 118118824Sharti TAILQ_FOREACH(aif, &diagif_list, link) 119118824Sharti if (strlen(aif->ifname) == 120118824Sharti sdl->sdl_nlen && 121118824Sharti strncmp(aif->ifname, sdl->sdl_data, 122118824Sharti sdl->sdl_nlen) == 0) 123118824Sharti break; 124118824Sharti if (aif == NULL) { 125118824Sharti warnx("interface '%.*s' not found", 126118824Sharti sdl->sdl_nlen, sdl->sdl_data); 127118824Sharti goto fail; 128118824Sharti } 129118824Sharti r->aif = aif; 130118824Sharti 131118824Sharti /* parse ATM stuff */ 132118824Sharti 133118824Sharti#define GET3() (((sdl->sdl_data[n] & 0xff) << 16) | \ 134118824Sharti ((sdl->sdl_data[n + 1] & 0xff) << 8) | \ 135118824Sharti ((sdl->sdl_data[n + 2] & 0xff) << 0)) 136118824Sharti#define GET2() (((sdl->sdl_data[n] & 0xff) << 8) | \ 137118824Sharti ((sdl->sdl_data[n + 1] & 0xff) << 0)) 138118824Sharti#define GET1() (((sdl->sdl_data[n] & 0xff) << 0)) 139118824Sharti 140118824Sharti n = sdl->sdl_nlen; 141118824Sharti if (sdl->sdl_alen < 4) { 142118824Sharti warnx("RTA_GATEWAY alen too short"); 143118824Sharti goto fail; 144118824Sharti } 145118824Sharti r->llcsnap = GET1() & ATM_PH_LLCSNAP; 146118824Sharti n++; 147118824Sharti r->vpi = GET1(); 148118824Sharti n++; 149118824Sharti r->vci = GET2(); 150118824Sharti n += 2; 151118824Sharti if (sdl->sdl_alen == 4) { 152118824Sharti /* old address */ 153118824Sharti r->traffic = ATMIO_TRAFFIC_UBR; 154118824Sharti r->pcr = 0; 155118824Sharti break; 156118824Sharti } 157118824Sharti /* new address */ 158118824Sharti r->traffic = GET1(); 159118824Sharti n++; 160118824Sharti switch (r->traffic) { 161118824Sharti 162118824Sharti case ATMIO_TRAFFIC_UBR: 163118824Sharti if (sdl->sdl_alen >= 5 + 3) { 164118824Sharti r->pcr = GET3(); 165118824Sharti n += 3; 166118824Sharti } else 167118824Sharti r->pcr = 0; 168118824Sharti break; 169118824Sharti 170118824Sharti case ATMIO_TRAFFIC_CBR: 171118824Sharti if (sdl->sdl_alen < 5 + 3) { 172118824Sharti warnx("CBR address too short"); 173118824Sharti goto fail; 174118824Sharti } 175118824Sharti r->pcr = GET3(); 176118824Sharti n += 3; 177118824Sharti break; 178118824Sharti 179118824Sharti case ATMIO_TRAFFIC_VBR: 180118824Sharti if (sdl->sdl_alen < 5 + 3 * 3) { 181118824Sharti warnx("VBR address too short"); 182118824Sharti goto fail; 183118824Sharti } 184118824Sharti r->pcr = GET3(); 185118824Sharti n += 3; 186118824Sharti r->scr = GET3(); 187118824Sharti n += 3; 188118824Sharti r->mbs = GET3(); 189118824Sharti n += 3; 190118824Sharti break; 191118824Sharti 192118824Sharti case ATMIO_TRAFFIC_ABR: 193118824Sharti if (sdl->sdl_alen < 5 + 4 * 3 + 2 + 194118824Sharti 1 * 2 + 3) { 195118824Sharti warnx("ABR address too short"); 196118824Sharti goto fail; 197118824Sharti } 198118824Sharti r->pcr = GET3(); 199118824Sharti n += 3; 200118824Sharti r->mcr = GET3(); 201118824Sharti n += 3; 202118824Sharti r->icr = GET3(); 203118824Sharti n += 3; 204118824Sharti r->tbe = GET3(); 205118824Sharti n += 3; 206118824Sharti r->nrm = GET1(); 207118824Sharti n++; 208118824Sharti r->trm = GET1(); 209118824Sharti n++; 210118824Sharti r->adtf = GET2(); 211118824Sharti n += 2; 212118824Sharti r->rif = GET1(); 213118824Sharti n++; 214118824Sharti r->rdf = GET1(); 215118824Sharti n++; 216118824Sharti r->cdf = GET1(); 217118824Sharti n++; 218118824Sharti break; 219118824Sharti 220118824Sharti default: 221118824Sharti goto fail; 222118824Sharti } 223118824Sharti break; 224118824Sharti } 225118824Sharti } 226118824Sharti } 227118824Sharti 228118824Sharti TAILQ_INSERT_TAIL(&natm_route_list, r, link); 229118824Sharti 230118824Sharti return; 231118824Sharti fail: 232118824Sharti free(r); 233118824Sharti} 234118824Sharti 235118824Sharti/* 236118824Sharti * Fetch the INET routes that a ours 237118824Sharti */ 238118824Shartistatic void 239118824Shartinatm_route_fetch(void) 240118824Sharti{ 241118824Sharti int name[6]; 242118824Sharti size_t needed; 243118824Sharti u_char *buf, *next; 244118824Sharti struct rt_msghdr *rtm; 245118824Sharti 246118824Sharti name[0] = CTL_NET; 247118824Sharti name[1] = PF_ROUTE; 248118824Sharti name[2] = 0; 249118824Sharti name[3] = AF_INET; 250118824Sharti name[4] = NET_RT_DUMP; 251118824Sharti name[5] = 0; 252118824Sharti 253118824Sharti if (sysctl(name, 6, NULL, &needed, NULL, 0) == -1) 254118824Sharti err(1, "rtable estimate"); 255118824Sharti needed *= 2; 256118824Sharti if ((buf = malloc(needed)) == NULL) 257118824Sharti err(1, "rtable buffer (%zu)", needed); 258118824Sharti if (sysctl(name, 6, buf, &needed, NULL, 0) == -1) 259118824Sharti err(1, "rtable get"); 260118824Sharti 261118824Sharti next = buf; 262118824Sharti while (next < buf + needed) { 263118824Sharti rtm = (struct rt_msghdr *)(void *)next; 264118824Sharti next += rtm->rtm_msglen; 265118824Sharti 266118824Sharti if (rtm->rtm_type == RTM_GET) { 267118824Sharti if ((rtm->rtm_flags & (RTF_UP | RTF_HOST | 268118824Sharti RTF_STATIC)) == (RTF_UP | RTF_HOST | RTF_STATIC) && 269118824Sharti (rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | 270118824Sharti RTA_IFP)) == (RTA_DST | RTA_GATEWAY | RTA_IFP)) 271118824Sharti store_route(rtm); 272118824Sharti } 273118824Sharti } 274118824Sharti} 275118824Sharti 276118824Shartistatic u_long 277118824Shartiparse_num(const char *arg, const char *name, u_long limit) 278118824Sharti{ 279118824Sharti u_long res; 280118824Sharti char *end; 281118824Sharti 282118824Sharti errno = 0; 283118824Sharti res = strtoul(arg, &end, 10); 284118824Sharti if (*end != '\0' || end == arg || errno != 0) 285118824Sharti errx(1, "cannot parse %s '%s'", name, arg); 286118824Sharti if (res > limit) 287118824Sharti errx(1, "%s out of range (0...%lu)", name, limit); 288118824Sharti return (res); 289118824Sharti} 290118824Sharti 291118824Shartistatic void 292118824Shartido_route(u_int type, u_int flags, const struct sockaddr_in *sain, 293118824Sharti const struct sockaddr_dl *sdl) 294118824Sharti{ 295118824Sharti struct { 296118824Sharti struct rt_msghdr h; 297118824Sharti char space[512]; 298118824Sharti } msg; 299118824Sharti char *ptr; 300118824Sharti int s; 301118824Sharti ssize_t rlen; 302118824Sharti 303118824Sharti /* create routing message */ 304118824Sharti bzero(&msg, sizeof(msg)); 305118824Sharti msg.h.rtm_msglen = sizeof(msg.h); 306118824Sharti msg.h.rtm_version = RTM_VERSION; 307118824Sharti msg.h.rtm_type = type; 308118824Sharti msg.h.rtm_index = 0; 309118824Sharti msg.h.rtm_flags = flags; 310118824Sharti msg.h.rtm_addrs = RTA_DST | (sdl != NULL ? RTA_GATEWAY : 0); 311118824Sharti msg.h.rtm_pid = getpid(); 312118824Sharti 313118824Sharti ptr = (char *)&msg + sizeof(msg.h); 314118824Sharti memcpy(ptr, sain, sain->sin_len); 315118824Sharti ptr += roundup(sain->sin_len, sizeof(long)); 316118824Sharti msg.h.rtm_msglen += roundup(sain->sin_len, sizeof(long)); 317118824Sharti 318118824Sharti if (sdl != NULL) { 319118824Sharti memcpy(ptr, sdl, sdl->sdl_len); 320118824Sharti ptr += roundup(sdl->sdl_len, sizeof(long)); 321118824Sharti msg.h.rtm_msglen += roundup(sdl->sdl_len, sizeof(long)); 322118824Sharti } 323118824Sharti 324118824Sharti /* open socket */ 325118824Sharti s = socket(PF_ROUTE, SOCK_RAW, AF_INET); 326118824Sharti if (s == -1) 327118824Sharti err(1, "cannot open routing socket"); 328118824Sharti 329118824Sharti rlen = write(s, &msg, msg.h.rtm_msglen); 330118824Sharti if (rlen == -1) 331118824Sharti err(1, "writing to routing socket"); 332118824Sharti if ((size_t)rlen != msg.h.rtm_msglen) 333118824Sharti errx(1, "short write to routing socket: %zu %u", 334118824Sharti (size_t)rlen, msg.h.rtm_msglen); 335118824Sharti close(s); 336118824Sharti} 337118824Sharti 338118824Sharti/* 339118824Sharti * Add a new NATM route 340118824Sharti */ 341118824Shartistatic void 342118824Shartinatm_add(int argc, char *argv[]) 343118824Sharti{ 344118824Sharti int opt; 345118824Sharti struct hostent *hp; 346118824Sharti struct sockaddr_in sain; 347118824Sharti struct sockaddr_dl sdl; 348118824Sharti struct diagif *aif; 349118824Sharti u_long num, num1; 350118824Sharti u_int idx; 351118824Sharti 352118824Sharti static int printonly; 353118824Sharti 354118824Sharti static const struct option opts[] = { 355118824Sharti { "printonly", OPT_SIMPLE, &printonly }, 356118824Sharti { NULL, 0, NULL } 357118824Sharti }; 358118824Sharti 359118824Sharti while ((opt = parse_options(&argc, &argv, opts)) != -1) 360118824Sharti switch (opt) { 361118824Sharti } 362118824Sharti 363118824Sharti if (argc < 5) 364118824Sharti errx(1, "missing arguments for 'natm add'"); 365118824Sharti 366118824Sharti memset(&sdl, 0, sizeof(sdl)); 367118824Sharti sdl.sdl_len = sizeof(sdl); 368118824Sharti sdl.sdl_family = AF_LINK; 369118824Sharti 370118824Sharti /* get the IP address for <dest> */ 371118824Sharti memset(&sain, 0, sizeof(sain)); 372118824Sharti hp = gethostbyname(argv[0]); 373118824Sharti if (hp == NULL) 374118824Sharti errx(1, "bad hostname %s: %s", argv[0], hstrerror(h_errno)); 375118824Sharti if (hp->h_addrtype != AF_INET) 376118824Sharti errx(1, "bad address type for %s", argv[0]); 377118824Sharti sain.sin_len = sizeof(sain); 378118824Sharti sain.sin_family = AF_INET; 379118824Sharti memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr)); 380118824Sharti 381118824Sharti /* find interface */ 382118824Sharti diagif_fetch(); 383118824Sharti TAILQ_FOREACH(aif, &diagif_list, link) 384118824Sharti if (strcmp(aif->ifname, argv[1]) == 0) 385118824Sharti break; 386118824Sharti if (aif == NULL) 387118824Sharti errx(1, "unknown ATM interface '%s'", argv[1]); 388118824Sharti sdl.sdl_index = aif->index; 389118824Sharti strcpy(sdl.sdl_data, aif->ifname); 390118824Sharti idx = sdl.sdl_nlen = strlen(aif->ifname); 391118824Sharti idx++; 392118824Sharti 393118824Sharti /* verify VPI/VCI */ 394118824Sharti num = parse_num(argv[2], "VPI", (1U << aif->mib.vpi_bits)); 395118824Sharti sdl.sdl_data[idx++] = num & 0xff; 396118824Sharti num = parse_num(argv[3], "VCI", (1U << aif->mib.vci_bits)); 397118824Sharti if (num == 0) 398118824Sharti errx(1, "VCI may not be 0"); 399118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 400118824Sharti sdl.sdl_data[idx++] = num & 0xff; 401118824Sharti 402118824Sharti /* encapsulation */ 403118824Sharti if (strcasecmp(argv[4], "llc/snap") == 0) { 404118824Sharti sdl.sdl_data[sdl.sdl_nlen] = ATM_PH_LLCSNAP; 405118824Sharti } else if (strcasecmp(argv[4], "aal5") == 0) { 406118824Sharti sdl.sdl_data[sdl.sdl_nlen] = 0; 407118824Sharti } else 408118824Sharti errx(1, "bad encapsulation type '%s'", argv[4]); 409118824Sharti 410118824Sharti /* look at the traffic */ 411118824Sharti argc -= 5; 412118824Sharti argv += 5; 413118824Sharti 414118824Sharti if (argc != 0) { 415118824Sharti if (strcasecmp(argv[0], "ubr") == 0) { 416118824Sharti sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR; 417118824Sharti if (argc == 1) 418118824Sharti /* ok */; 419118824Sharti else if (argc == 2) { 420118824Sharti num = parse_num(argv[1], "PCR", aif->mib.pcr); 421118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 422118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 423118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 424118824Sharti } else 425118824Sharti errx(1, "too many parameters for UBR"); 426118824Sharti 427118824Sharti } else if (strcasecmp(argv[0], "cbr") == 0) { 428118824Sharti sdl.sdl_data[idx++] = ATMIO_TRAFFIC_CBR; 429118824Sharti if (argc == 1) 430118824Sharti errx(1, "missing PCR for CBR"); 431118824Sharti if (argc > 2) 432118824Sharti errx(1, "too many parameters for CBR"); 433118824Sharti num = parse_num(argv[1], "PCR", aif->mib.pcr); 434118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 435118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 436118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 437118824Sharti 438118824Sharti } else if (strcasecmp(argv[0], "vbr") == 0) { 439118824Sharti sdl.sdl_data[idx++] = ATMIO_TRAFFIC_VBR; 440118824Sharti 441118824Sharti if (argc < 4) 442118824Sharti errx(1, "missing arg(s) for VBR"); 443118824Sharti if (argc > 4) 444118824Sharti errx(1, "too many parameters for VBR"); 445118824Sharti 446118824Sharti num = parse_num(argv[1], "PCR", aif->mib.pcr); 447118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 448118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 449118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 450118824Sharti num = parse_num(argv[2], "SCR", num); 451118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 452118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 453118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 454118824Sharti num = parse_num(argv[3], "MBS", 0xffffffLU); 455118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 456118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 457118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 458118824Sharti 459118824Sharti } else if (strcasecmp(argv[0], "abr") == 0) { 460118824Sharti sdl.sdl_data[idx++] = ATMIO_TRAFFIC_ABR; 461118824Sharti if (argc < 11) 462118824Sharti errx(1, "missing arg(s) for ABR"); 463118824Sharti if (argc > 11) 464118824Sharti errx(1, "too many parameters for ABR"); 465118824Sharti 466118824Sharti num = parse_num(argv[1], "PCR", aif->mib.pcr); 467118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 468118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 469118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 470118824Sharti 471118824Sharti num1 = parse_num(argv[2], "MCR", num); 472118824Sharti sdl.sdl_data[idx++] = (num1 >> 16) & 0xff; 473118824Sharti sdl.sdl_data[idx++] = (num1 >> 8) & 0xff; 474118824Sharti sdl.sdl_data[idx++] = (num1 >> 0) & 0xff; 475118824Sharti 476118824Sharti num = parse_num(argv[3], "ICR", num); 477118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 478118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 479118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 480118824Sharti 481118824Sharti if (num < num1) 482118824Sharti errx(1, "ICR must be >= MCR"); 483118824Sharti 484118824Sharti num = parse_num(argv[4], "TBE", 0xffffffUL); 485118824Sharti sdl.sdl_data[idx++] = (num >> 16) & 0xff; 486118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 487118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 488118824Sharti 489118824Sharti num = parse_num(argv[5], "NRM", 0x7UL); 490118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 491118824Sharti 492118824Sharti num = parse_num(argv[6], "TRM", 0x7UL); 493118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 494118824Sharti 495118824Sharti num = parse_num(argv[7], "ADTF", 0x3ffUL); 496118824Sharti sdl.sdl_data[idx++] = (num >> 8) & 0xff; 497118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 498118824Sharti 499118824Sharti num = parse_num(argv[8], "RIF", 0xfUL); 500118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 501118824Sharti 502118824Sharti num = parse_num(argv[9], "RDF", 0xfUL); 503118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 504118824Sharti 505118824Sharti num = parse_num(argv[10], "CDF", 0x7UL); 506118824Sharti sdl.sdl_data[idx++] = (num >> 0) & 0xff; 507118824Sharti 508118824Sharti } else 509118824Sharti errx(1, "bad traffic type '%s'", argv[0]); 510118824Sharti } else 511118824Sharti sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR; 512118824Sharti 513118824Sharti sdl.sdl_alen = idx - sdl.sdl_nlen; 514118824Sharti sdl.sdl_len += sdl.sdl_nlen + sdl.sdl_alen; 515118824Sharti 516118824Sharti if (printonly) { 517118824Sharti printf("route add -iface %s -link %.*s", 518118824Sharti inet_ntoa(sain.sin_addr), sdl.sdl_nlen, sdl.sdl_data); 519118824Sharti for (idx = 0; idx < sdl.sdl_alen; idx++) 520118824Sharti printf("%c%x", ".:"[idx == 0], 521118824Sharti (u_int)sdl.sdl_data[sdl.sdl_nlen + idx] & 0xffU); 522118824Sharti printf("\n"); 523118824Sharti exit(0); 524118824Sharti } 525118824Sharti 526118824Sharti do_route(RTM_ADD, RTF_HOST | RTF_STATIC | RTF_UP, &sain, &sdl); 527118824Sharti} 528118824Sharti 529118824Sharti/* 530118824Sharti * Delete an NATM route 531118824Sharti */ 532118824Shartistatic void 533118824Shartinatm_delete(int argc, char *argv[]) 534118824Sharti{ 535118824Sharti int opt; 536118824Sharti struct hostent *hp; 537118824Sharti struct sockaddr_in sain; 538118824Sharti u_int vpi, vci; 539118824Sharti struct diagif *aif; 540118824Sharti struct natm_route *r; 541118824Sharti 542118824Sharti static int printonly; 543118824Sharti 544118824Sharti static const struct option opts[] = { 545118824Sharti { "printonly", OPT_SIMPLE, &printonly }, 546118824Sharti { NULL, 0, NULL } 547118824Sharti }; 548118824Sharti 549118824Sharti while ((opt = parse_options(&argc, &argv, opts)) != -1) 550118824Sharti switch (opt) { 551118824Sharti } 552118824Sharti 553118824Sharti diagif_fetch(); 554118824Sharti natm_route_fetch(); 555118824Sharti 556118824Sharti memset(&sain, 0, sizeof(sain)); 557118824Sharti sain.sin_len = sizeof(sain); 558118824Sharti sain.sin_family = AF_INET; 559118824Sharti 560118824Sharti if (argc == 1) { 561118824Sharti /* get the IP address for <dest> */ 562118824Sharti hp = gethostbyname(argv[0]); 563118824Sharti if (hp == NULL) 564118824Sharti errx(1, "bad hostname %s: %s", argv[0], 565118824Sharti hstrerror(h_errno)); 566118824Sharti if (hp->h_addrtype != AF_INET) 567118824Sharti errx(1, "bad address type for %s", argv[0]); 568118824Sharti memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr)); 569118824Sharti 570118824Sharti TAILQ_FOREACH(r, &natm_route_list, link) 571118824Sharti if (r->host.s_addr == sain.sin_addr.s_addr) 572118824Sharti break; 573118824Sharti if (r == NULL) 574118824Sharti errx(1, "no NATM route to host '%s' (%s)", argv[0], 575118824Sharti inet_ntoa(sain.sin_addr)); 576118824Sharti 577118824Sharti } else if (argc == 3) { 578118824Sharti TAILQ_FOREACH(aif, &diagif_list, link) 579118824Sharti if (strcmp(aif->ifname, argv[0]) == 0) 580118824Sharti break; 581118824Sharti if (aif == 0) 582118824Sharti errx(1, "no such interface '%s'", argv[0]); 583118824Sharti 584118824Sharti vpi = parse_num(argv[1], "VPI", 0xff); 585118824Sharti vci = parse_num(argv[2], "VCI", 0xffff); 586118824Sharti 587118824Sharti TAILQ_FOREACH(r, &natm_route_list, link) 588118824Sharti if (r->aif == aif && r->vpi == vpi && r->vci == vci) 589118824Sharti break; 590118824Sharti if (r == NULL) 591118824Sharti errx(1, "no such NATM route %s %u %u", argv[0], 592118824Sharti vpi, vci); 593118824Sharti sain.sin_addr = r->host; 594118824Sharti 595118824Sharti } else 596118824Sharti errx(1, "bad number of arguments for 'natm delete'"); 597118824Sharti 598118824Sharti if (printonly) { 599118824Sharti printf("route delete %s\n", inet_ntoa(r->host)); 600118824Sharti exit(0); 601118824Sharti } 602118824Sharti 603118824Sharti do_route(RTM_DELETE, r->flags, &sain, NULL); 604118824Sharti} 605118824Sharti 606118824Sharti/* 607118824Sharti * Show NATM routes 608118824Sharti */ 609118824Shartistatic void 610118824Shartinatm_show(int argc, char *argv[]) 611118824Sharti{ 612118824Sharti int opt; 613118824Sharti struct natm_route *r; 614118824Sharti struct hostent *hp; 615118824Sharti 616118824Sharti static const char *const traffics[] = { 617118824Sharti [ATMIO_TRAFFIC_UBR] = "UBR", 618118824Sharti [ATMIO_TRAFFIC_CBR] = "CBR", 619118824Sharti [ATMIO_TRAFFIC_VBR] = "VBR", 620118824Sharti [ATMIO_TRAFFIC_ABR] = "ABR" 621118824Sharti }; 622118824Sharti 623118824Sharti static int numeric, abr; 624118824Sharti 625118824Sharti static const struct option opts[] = { 626118824Sharti { "abr", OPT_SIMPLE, &abr }, 627118824Sharti { "numeric", OPT_SIMPLE, &numeric }, 628118824Sharti { NULL, 0, NULL } 629118824Sharti }; 630118824Sharti 631118824Sharti static const char head[] = 632118824Sharti "Destination Iface VPI VCI Encaps Trf PCR " 633118824Sharti "SCR/MCR MBS/ICR\n"; 634118824Sharti static const char head_abr[] = 635118824Sharti "Destination Iface VPI VCI Encaps Trf PCR " 636118824Sharti "SCR/MCR MBS/ICR TBE NRM TRM ADTF RIF RDF CDF\n"; 637118824Sharti 638118824Sharti while ((opt = parse_options(&argc, &argv, opts)) != -1) 639118824Sharti switch (opt) { 640118824Sharti } 641118824Sharti 642118824Sharti diagif_fetch(); 643118824Sharti natm_route_fetch(); 644118824Sharti 645118824Sharti heading_init(); 646118824Sharti TAILQ_FOREACH(r, &natm_route_list, link) { 647118824Sharti heading(abr ? head_abr : head); 648118824Sharti if (numeric) 649118824Sharti printf("%-20s", inet_ntoa(r->host)); 650118824Sharti else if (r->host.s_addr == INADDR_ANY) 651118824Sharti printf("%-20s", "default"); 652118824Sharti else { 653118824Sharti hp = gethostbyaddr((char *)&r->host, sizeof(r->host), 654118824Sharti AF_INET); 655118824Sharti if (hp != NULL) 656118824Sharti printf("%-20s", hp->h_name); 657118824Sharti else 658118824Sharti printf("%-20s", inet_ntoa(r->host)); 659118824Sharti } 660118824Sharti printf("%-12s%-4u%-6u%-9s%-4s", r->aif->ifname, r->vpi, r->vci, 661118824Sharti r->llcsnap ? "LLC/SNAP" : "AAL5", traffics[r->traffic]); 662118824Sharti switch (r->traffic) { 663118824Sharti 664118824Sharti case ATMIO_TRAFFIC_UBR: 665118824Sharti case ATMIO_TRAFFIC_CBR: 666118824Sharti printf("%-8u", r->pcr); 667118824Sharti break; 668118824Sharti 669118824Sharti case ATMIO_TRAFFIC_VBR: 670118824Sharti printf("%-8u%-8u%-8u", r->pcr, r->scr, r->mbs); 671118824Sharti break; 672118824Sharti 673118824Sharti case ATMIO_TRAFFIC_ABR: 674118824Sharti printf("%-8u%-8u%-8u", r->pcr, r->mcr, r->icr); 675118824Sharti if (abr) 676118824Sharti printf("%-8u%-4u%-4u%-5u%-4u%-4u%-4u", 677118824Sharti r->tbe, r->nrm, r->trm, r->adtf, 678118824Sharti r->rif, r->rdf, r->cdf); 679118824Sharti break; 680118824Sharti } 681118824Sharti printf("\n"); 682118824Sharti } 683118824Sharti} 684