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