1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)if_x25subr.c 7.8 (Berkeley) 01/09/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "malloc.h" 13 #include "mbuf.h" 14 #include "protosw.h" 15 #include "socket.h" 16 #include "socketvar.h" 17 #include "ioctl.h" 18 #include "errno.h" 19 #include "syslog.h" 20 21 #include "../net/if.h" 22 #include "../net/if_types.h" 23 #include "../net/netisr.h" 24 #include "../net/route.h" 25 26 #include "x25.h" 27 #include "x25err.h" 28 #include "pk.h" 29 #include "pk_var.h" 30 31 #include "machine/mtpr.h" 32 33 #ifdef INET 34 #include "../netinet/in.h" 35 #include "../netinet/in_var.h" 36 #endif 37 38 #ifdef NS 39 #include "../netns/ns.h" 40 #include "../netns/ns_if.h" 41 #endif 42 43 #ifdef ISO 44 #include "../netiso/argo_debug.h" 45 #include "../netiso/iso.h" 46 #include "../netiso/iso_var.h" 47 #endif 48 49 extern struct ifnet loif; 50 51 #define senderr(x) {error = x; goto bad;} 52 /* 53 * X.25 output routine. 54 */ 55 x25_ifoutput(ifp, m0, dst, rt) 56 struct ifnet *ifp; 57 struct mbuf *m0; 58 struct sockaddr *dst; 59 register struct rtentry *rt; 60 { 61 register struct mbuf *m; 62 register struct llinfo_x25 *lx; 63 register struct pq *pq; 64 struct pklcd *lcp; 65 struct x25_ifaddr *ia; 66 struct mbuf *prev; 67 int s, error = 0, flags = 0, af; 68 69 if ((ifp->if_flags & IFF_UP) == 0) 70 return (ENETDOWN); 71 if (rt == 0 || 72 ((rt->rt_flags & RTF_GATEWAY) && (dst = rt->rt_gateway))) { 73 if ((rt = rtalloc1(dst, 1)) == 0) 74 return (EHOSTUNREACH); 75 rt->rt_refcnt++; 76 flags = LXF_RTHELD; 77 } 78 /* 79 * Sanity checks. 80 */ 81 if ((rt->rt_ifp != ifp) || 82 (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) || 83 ((lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)) { 84 printf("Inconsistent call to x25_output, should panic\n"); 85 senderr(ENETUNREACH); 86 } 87 { 88 register struct ifaddr *ifa; 89 for (ifa = ifp->if_addrlist; ; ifa = ifa->ifa_next) { 90 if (ifa == 0) 91 senderr(ENETDOWN); 92 if (ifa->ifa_addr->sa_family == AF_CCITT) 93 break; 94 } 95 ia = (struct x25_ifaddr *)ifa; 96 } 97 switch (lx->lx_state) { 98 99 case LXS_CONNECTED: 100 lcp->lcd_dg_timer = ia->ia_xc.xc_dg_idletimo; 101 /* FALLTHROUGH */ 102 case LXS_CONNECTING: 103 if (sbspace(&lcp->lcd_sb) < 0) 104 senderr(ENOBUFS); 105 lcp->lcd_send(lcp, m); 106 break; 107 108 case LXS_NEWBORN: 109 if (dst->sa_family == AF_INET && 110 ia->ia_ifp->if_type == IFT_X25DDN && 111 rt->rt_gateway->sa_family != AF_CCITT) 112 x25_ddnip_to_ccitt(dst, rt->rt_gateway); 113 lcp->lcd_flags |= X25_DG_CIRCUIT; 114 lx->lx_state = LXS_FREE; 115 if (rt->rt_gateway->sa_family != AF_CCITT) { 116 /* 117 * Need external resolution of dst 118 */ 119 if ((rt->rt_flags & RTF_XRESOLVE) == 0) 120 senderr(ENETUNREACH); 121 lx->lx_flags |= flags; 122 flags = 0; 123 rt_missmsg(RTM_RESOLVE, dst, 124 (struct sockaddr *)0, (struct sockaddr *)0, 125 (struct sockaddr *)0, 0, 0); 126 lx->lx_state = LXS_RESOLVING; 127 /* FALLTHROUGH */ 128 case LXS_RESOLVING: 129 if (sbspace(&lcp->lcd_sb) < 0) 130 senderr(ENOBUFS); 131 pk_fragment(lcp, m, 0, 0, 0); 132 break; 133 } 134 /* FALLTHROUGH */ 135 case LXS_FREE: 136 lcp->lcd_pkp = &(lx->lx_ia->ia_pkcb); 137 pk_fragment(lcp, m, 0, 0, 0); 138 pk_connect(lcp, (struct sockaddr_x25 *)rt->rt_gateway); 139 break; 140 /* FALLTHROUGH */ 141 default: 142 /* 143 * We count on the timer routine to close idle 144 * connections, if there are not enough circuits to go 145 * around. 146 * 147 * So throw away data for now. 148 * After we get it all working, we'll rewrite to handle 149 * actively closing connections (other than by timers), 150 * when circuits get tight. 151 * 152 * In the DDN case, the imp itself closes connections 153 * under heavy load. 154 */ 155 error = ENOBUFS; 156 bad: 157 if (m) 158 m_freem(m); 159 } 160 out: 161 if (flags & LXF_RTHELD) 162 RTFREE(rt); 163 return (error); 164 } 165 166 /* 167 * Simpleminded timer routine. 168 */ 169 x25_iftimeout(ifp) 170 struct ifnet *ifp; 171 { 172 register struct pkcb *pkcb = 0; 173 register struct ifaddr *ifa; 174 register struct pklcd **lcpp, *lcp; 175 int s = splimp(); 176 177 for (ifa = ifp->if_addrlist; ; ifa = ifa->ifa_next) { 178 if (ifa->ifa_addr->sa_family == AF_CCITT) 179 break; 180 } 181 if (ifa) 182 pkcb = &((struct x25_ifaddr *)ifa)->ia_pkcb; 183 if (pkcb) 184 for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn; 185 --lcpp > pkcb->pk_chan;) 186 if ((lcp = *lcpp) && 187 lcp->lcd_state == DATA_TRANSFER && 188 (lcp->lcd_flags & X25_DG_CIRCUIT) && 189 (lcp->lcd_dg_timer && --lcp->lcd_dg_timer == 0)) { 190 pk_disconnect(lcp); 191 } 192 splx(s); 193 } 194 195 /* 196 * Process a x25 packet as datagram; 197 */ 198 x25_ifinput(lcp, m) 199 struct pklcd *lcp; 200 register struct mbuf *m; 201 { 202 struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext; 203 register struct ifnet *ifp = m->m_pkthdr.rcvif; 204 struct ifqueue *inq; 205 struct rtentry *rt; 206 extern struct timeval time; 207 int s, len; 208 209 if (m == 0) 210 goto trouble; 211 ifp = m->m_pkthdr.rcvif; 212 ifp->if_lastchange = time; 213 switch (m->m_type) { 214 trouble: 215 case MT_CONTROL: 216 if (lcp->lcd_state != DATA_TRANSFER) { 217 lx->lx_lcd = 0; 218 if (lx->lx_rt == 0) 219 FREE(lx, M_PCB); 220 pk_close(lcp); 221 } 222 case MT_OOBDATA: 223 if (m) 224 m_freem(m); 225 return; 226 } 227 228 switch (lx->lx_family) { 229 #ifdef INET 230 case AF_INET: 231 schednetisr(NETISR_IP); 232 inq = &ipintrq; 233 break; 234 235 #endif 236 #ifdef NS 237 case AF_NS: 238 schednetisr(NETISR_NS); 239 inq = &nsintrq; 240 break; 241 242 #endif 243 #ifdef ISO 244 case AF_ISO: 245 schednetisr(NETISR_ISO); 246 inq = &clnlintrq; 247 break; 248 #endif 249 default: 250 m_freem(m); 251 ifp->if_noproto++; 252 return; 253 } 254 s = splimp(); 255 if (IF_QFULL(inq)) { 256 IF_DROP(inq); 257 m_freem(m); 258 } else { 259 IF_ENQUEUE(inq, m); 260 ifp->if_ibytes += m->m_pkthdr.len; 261 } 262 splx(s); 263 } 264 265 /* 266 * This routine gets called when validing new routes or deletions of old 267 * ones. 268 */ 269 x25_ifrtchange(cmd, rt, dst) 270 register struct rtentry *rt; 271 struct sockaddr *dst; 272 { 273 register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo; 274 register struct sockaddr_x25 *sa =(struct sockaddr_x25 *)rt->rt_gateway; 275 register struct pklcd *lcp; 276 register struct x25_ifaddr *ia; 277 register struct sockaddr *sa2; 278 int x25_ifinput(); 279 #define SA(p) ((struct sockaddr *)(p)) 280 281 if (lx == 0) { 282 MALLOC(lx, struct llinfo_x25 *, sizeof (*lx), M_PCB, M_NOWAIT); 283 if (lx == 0) 284 return; 285 Bzero(lx, sizeof(*lx)); 286 rt->rt_llinfo = (caddr_t)lx; 287 rt->rt_refcnt++; 288 lx->lx_rt = rt; 289 lx->lx_ia = (struct x25_ifaddr *)rt->rt_ifa; 290 } 291 lcp = lx->lx_lcd; 292 if (cmd == RTM_DELETE) { 293 if (lcp) 294 pk_disconnect(lcp); 295 rt->rt_refcnt--; 296 rt->rt_llinfo = 0; 297 FREE(lx, M_PCB); 298 return; 299 } 300 if (lcp && lcp->lcd_state != READY) { 301 pk_disconnect(lcp); 302 lcp = 0; 303 } 304 if (lcp == 0) { 305 if (rt->rt_flags & RTF_XRESOLVE || sa->x25_family != AF_CCITT) 306 return; 307 lx->lx_lcd = lcp = pk_attach((struct socket *)0); 308 ia = lx->lx_ia; 309 if (lcp == 0) 310 return; 311 lcp->lcd_upnext = (caddr_t)lx; 312 lcp->lcd_upper = x25_ifinput; 313 lcp->lcd_packetsize = ia->ia_xc.xc_psize; /* XXX pk_fragment */ 314 lcp->lcd_pkp = &(ia->ia_pkcb); 315 } 316 pk_connect(lcp, sa); 317 if (rt->rt_ifp->if_type == IFT_X25DDN) 318 return; 319 sa2 = rt_key(rt); 320 if (cmd == RTM_CHANGE) { 321 if (sa->x25_family == AF_CCITT) { 322 sa->x25_opts.op_speed = sa2->sa_family; 323 (void) rtrequest(RTM_DELETE, SA(sa), sa2, 324 SA(0), RTF_HOST, (struct rtentry **)0); 325 } 326 sa = (struct sockaddr_x25 *)dst; 327 cmd = RTM_ADD; 328 } 329 if (sa->x25_family == AF_CCITT) { 330 sa->x25_opts.op_speed = sa2->sa_family; 331 (void) rtrequest(cmd, SA(sa), sa2, SA(0), RTF_HOST, 332 (struct rtentry **)0); 333 sa->x25_opts.op_speed = 0; 334 } 335 } 336 337 static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT}; 338 /* 339 * IP to X25 address routine copyright ACC, used by permission. 340 */ 341 union imp_addr { 342 struct in_addr ip; 343 struct imp { 344 u_char s_net; 345 u_char s_host; 346 u_char s_lh; 347 u_char s_impno; 348 } imp; 349 }; 350 351 x25_ddnip_to_ccitt(src, dst) 352 struct sockaddr_in *src; 353 register struct sockaddr_x25 *dst; 354 { 355 union imp_addr imp_addr; 356 int imp_no, imp_port, temp; 357 char *x25addr = dst->x25_addr; 358 359 360 imp_addr.ip = src->sin_addr; 361 *dst = blank_x25; 362 if ((imp_addr.imp.s_net & 0x80) == 0x00) { /* class A */ 363 imp_no = imp_addr.imp.s_impno; 364 imp_port = imp_addr.imp.s_host; 365 } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { /* class B */ 366 imp_no = imp_addr.imp.s_impno; 367 imp_port = imp_addr.imp.s_lh; 368 } else { /* class C */ 369 imp_no = imp_addr.imp.s_impno / 32; 370 imp_port = imp_addr.imp.s_impno % 32; 371 } 372 373 x25addr[0] = 12; /* length */ 374 /* DNIC is cleared by struct copy above */ 375 376 if (imp_port < 64) { /* Physical: 0000 0 IIIHH00 [SS] *//* s_impno 377 * -> III, s_host -> HH */ 378 x25addr[5] = 0; /* set flag bit */ 379 x25addr[6] = imp_no / 100; 380 x25addr[7] = (imp_no % 100) / 10; 381 x25addr[8] = imp_no % 10; 382 x25addr[9] = imp_port / 10; 383 x25addr[10] = imp_port % 10; 384 } else { /* Logical: 0000 1 RRRRR00 [SS] *//* s 385 * _host * 256 + s_impno -> RRRRR */ 386 temp = (imp_port << 8) + imp_no; 387 x25addr[5] = 1; 388 x25addr[6] = temp / 10000; 389 x25addr[7] = (temp % 10000) / 1000; 390 x25addr[8] = (temp % 1000) / 100; 391 x25addr[9] = (temp % 100) / 10; 392 x25addr[10] = temp % 10; 393 } 394 } 395 396 static struct sockaddr_in sin = {sizeof(sin), AF_INET}; 397 /* 398 * This routine is a sketch and is not to be believed!!!!! 399 * 400 * This is a utility routine to be called by x25 devices when a 401 * call request is honored with the intent of starting datagram forwarding. 402 */ 403 x25_dg_rtinit(dst, ia, af) 404 struct sockaddr_x25 *dst; 405 register struct x25_ifaddr *ia; 406 { 407 struct sockaddr *sa = 0; 408 struct rtentry *rt; 409 struct in_addr my_addr; 410 411 if (ia->ia_ifp->if_type == IFT_X25DDN && af == AF_INET) { 412 /* 413 * Inverse X25 to IP mapping copyright and courtesy ACC. 414 */ 415 int imp_no, imp_port, temp; 416 union imp_addr imp_addr; 417 { 418 /* 419 * First determine our IP addr for network 420 */ 421 register struct in_ifaddr *ina; 422 extern struct in_ifaddr *in_ifaddr; 423 424 for (ina = in_ifaddr; ina; ina = ina->ia_next) 425 if (ina->ia_ifp == ia->ia_ifp) { 426 my_addr = ina->ia_addr.sin_addr; 427 break; 428 } 429 } 430 { 431 432 register char *x25addr = dst->x25_addr; 433 434 switch (x25addr[5] & 0x0f) { 435 case 0: /* Physical: 0000 0 IIIHH00 [SS] */ 436 imp_no = 437 ((int) (x25addr[6] & 0x0f) * 100) + 438 ((int) (x25addr[7] & 0x0f) * 10) + 439 ((int) (x25addr[8] & 0x0f)); 440 441 442 imp_port = 443 ((int) (x25addr[9] & 0x0f) * 10) + 444 ((int) (x25addr[10] & 0x0f)); 445 break; 446 case 1: /* Logical: 0000 1 RRRRR00 [SS] */ 447 temp = ((int) (x25addr[6] & 0x0f) * 10000) 448 + ((int) (x25addr[7] & 0x0f) * 1000) 449 + ((int) (x25addr[8] & 0x0f) * 100) 450 + ((int) (x25addr[9] & 0x0f) * 10) 451 + ((int) (x25addr[10] & 0x0f)); 452 453 imp_port = temp >> 8; 454 imp_no = temp & 0xff; 455 break; 456 default: 457 return (0L); 458 } 459 imp_addr.ip = my_addr; 460 if ((imp_addr.imp.s_net & 0x80) == 0x00) { 461 /* class A */ 462 imp_addr.imp.s_host = imp_port; 463 imp_addr.imp.s_impno = imp_no; 464 imp_addr.imp.s_lh = 0; 465 } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { 466 /* class B */ 467 imp_addr.imp.s_lh = imp_port; 468 imp_addr.imp.s_impno = imp_no; 469 } else { 470 /* class C */ 471 imp_addr.imp.s_impno = (imp_no << 5) + imp_port; 472 } 473 } 474 sin.sin_addr = imp_addr.ip; 475 sa = (struct sockaddr *)&sin; 476 } else { 477 /* 478 * This uses the X25 routing table to do inverse 479 * lookup of x25 address to sockaddr. 480 */ 481 dst->x25_opts.op_speed = af; 482 if (rt = rtalloc1(dst, 0)) { 483 sa = rt->rt_gateway; 484 rt->rt_refcnt--; 485 } 486 dst->x25_opts.op_speed = 0; 487 } 488 /* 489 * Call to rtalloc1 will create rtentry for reverse path 490 * to callee by virtue of cloning magic and will allocate 491 * space for local control block. 492 */ 493 if (sa && (rt = rtalloc1(sa, 1))) 494 rt->rt_refcnt--; 495 } 496 497 struct radix_tree_head *x25_rnhead; 498 499 pk_init() 500 { 501 /* 502 * warning, sizeof (struct sockaddr_x25) > 32, 503 * but contains no data of interest beyond 32 504 */ 505 rn_inithead(&x25_rnhead, 16, AF_CCITT); 506 } 507