|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1996 Apple Computer, Inc. ! 27: * ! 28: * The information contained herein is subject to change without ! 29: * notice and should not be construed as a commitment by Apple ! 30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility ! 31: * for any errors that may appear. ! 32: * ! 33: * Confidential and Proprietary to Apple Computer, Inc. ! 34: * ! 35: * File: aurpd.c ! 36: */ ! 37: ! 38: /* ! 39: * Kernel process to implement the AURP daemon: ! 40: * manage tunnels to remote AURP servers across IP networks ! 41: */ ! 42: #ifdef _AIX ! 43: #include <sys/sleep.h> ! 44: #endif ! 45: #include <sysglue.h> ! 46: #ifdef _AIX ! 47: #include <sys/atomic_op.h> ! 48: #endif ! 49: #include <sys/socket.h> ! 50: #include <sys/socketvar.h> ! 51: #include <sys/protosw.h> ! 52: #include <sys/errno.h> ! 53: #include <netinet/in.h> ! 54: #include <at/appletalk.h> ! 55: #include <lap.h> ! 56: #include <routing_tables.h> ! 57: #define _AURP ! 58: #define _KERNSYS ! 59: #include <at/aurp.h> ! 60: #include <at_aurp.h> ! 61: ! 62: ! 63: #undef e_sleep_thread ! 64: #define M_RCVBUF (64 * 1024) ! 65: #define M_SNDBUF (64 * 1024) ! 66: struct aurp_global_t aurp_global; ! 67: /* ! 68: * Initialize the aurp pipe - ! 69: * -Create, initialize, and start the aurpd kernel process; we need ! 70: * a process to permit queueing between the socket and the stream, ! 71: * which is necessary for orderly access to the socket structure. ! 72: * -The user process (aurpd) is there to 'build' the AURP ! 73: * stream, act as a 'logging agent' (:-}), and hold open the stream ! 74: * during its use. ! 75: * -Data and AURP packets from the DDP stream will be fed into the ! 76: * UDP tunnel (AURPsend()) ! 77: * -Data and AURP packets from the UDP tunnel will be fed into the ! 78: * DDP stream (ip_to_atalk(), via the kernel process). ! 79: */ ! 80: aurpd_start() ! 81: { register int error; ! 82: register struct socket *so; ! 83: int maxbuf; ! 84: extern void aurp_wakeup(caddr_t, int); ! 85: /****### TEMPO HACK 9/26: we need more args than that for suser in bsd4.4 ! 86: if (!suser()) ! 87: return(EPERM); ! 88: */ ! 89: ! 90: /* ! 91: * Set up state prior to starting kernel process so we can back out ! 92: * (error return) if something goes wrong. ! 93: */ ! 94: bzero((char *)&aurp_global.tunnel, sizeof(aurp_global.tunnel)); ! 95: /*lock_alloc(&aurp_global.glock, LOCK_ALLOC_PIN, AURP_EVNT_LOCK, -1);*/ ! 96: ATLOCKINIT(aurp_global.glock); ! 97: ATEVENTINIT(aurp_global.event_anchor); ! 98: ! 99: /* open udp socket */ ! 100: if (aurp_global.udp_port == 0) ! 101: aurp_global.udp_port = AURP_SOCKNUM; ! 102: error = socreate(AF_INET, &aurp_global.tunnel, SOCK_DGRAM, ! 103: IPPROTO_UDP); ! 104: if (error) ! 105: { dPrintf(D_M_AURP, D_L_FATAL, ("AURP: Can't get socket (%d)\n", ! 106: error)); ! 107: return(error); ! 108: } ! 109: ! 110: so = aurp_global.tunnel; ! 111: ! 112: if (error = aurp_bindrp(so)) ! 113: { dPrintf(D_M_AURP, D_L_FATAL, ! 114: ("AURP: Can't bind to port %d (%d)\n", ! 115: &aurp_global.udp_port, error)); ! 116: soclose(so); ! 117: return(error); ! 118: } ! 119: ! 120: #ifdef _AIX ! 121: SOCKET_LOCK(so); ! 122: #else ! 123: sblock(&so->so_rcv, M_WAIT); ! 124: sblock(&so->so_snd, M_WAIT); ! 125: #endif ! 126: maxbuf = M_RCVBUF; ! 127: setsockopt(so,SOL_SOCKET,SO_RCVBUF,&maxbuf,sizeof(maxbuf)); ! 128: maxbuf = M_SNDBUF; ! 129: setsockopt(so,SOL_SOCKET,SO_SNDBUF,&maxbuf,sizeof(maxbuf)); ! 130: #ifdef _AIX ! 131: so->so_snd.sb_wakeup = 0; ! 132: so->so_snd.sb_wakearg = 0; ! 133: so->so_rcv.sb_wakeup = aurp_wakeup; ! 134: so->so_rcv.sb_wakearg = (caddr_t)AE_UDPIP; /* Yuck */ ! 135: so->so_rcv.sb_iodone = 0; ! 136: so->so_rcv.sb_ioarg = 0; ! 137: #else ! 138: so->so_upcall = aurp_wakeup; ! 139: so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */ ! 140: #endif ! 141: ! 142: so->so_state |= SS_NBIO; ! 143: #ifdef _AIX ! 144: so->so_special |=(SP_NOUAREA|SP_EXTPRIV); ! 145: #else ! 146: kprintf("aurpd: warning what do we do with so_special?"); ! 147: #endif ! 148: so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR); ! 149: so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR); ! 150: #ifdef _AIX ! 151: SOCKET_UNLOCK(so); ! 152: #else ! 153: sbunlock(&so->so_snd); ! 154: sbunlock(&so->so_rcv); ! 155: #endif ! 156: ! 157: return(0); ! 158: } ! 159: ! 160: AURPgetmsg(err) ! 161: int *err; ! 162: { register struct socket *so; ! 163: register int s, events; ! 164: ! 165: so = aurp_global.tunnel; ! 166: ! 167: for (;;) ! 168: { gbuf_t *from, *p_mbuf; ! 169: #ifdef _AIX ! 170: int flags = MSG_NONBLOCK; ! 171: #else ! 172: int flags = MSG_DONTWAIT; ! 173: #endif ! 174: struct uio auio; ! 175: ! 176: /* ! 177: * Wait for a package to arrive. This will be from the ! 178: * IP side - sowakeup() calls aurp_wakeup() ! 179: * when a packet arrives ! 180: */ ! 181: ! 182: ATDISABLE(s, aurp_global.glock); ! 183: events = aurp_global.event; ! 184: if (events == 0) ! 185: { ! 186: #ifdef _AIX ! 187: e_sleep_thread(&aurp_global.event_anchor, ! 188: &aurp_global.glock, LOCK_HANDLER); ! 189: #else ! 190: (void) tsleep(&aurp_global.event_anchor, PSOCK, "AURPgetmsg", 0); ! 191: #endif ! 192: events = aurp_global.event; ! 193: aurp_global.event = 0; ! 194: } ! 195: ATENABLE(s, aurp_global.glock); ! 196: ! 197: if (events & AE_SHUTDOWN) ! 198: { ! 199: aurp_global.shutdown = 1; ! 200: while (aurp_global.running) ! 201: ; ! 202: /*lock_free(&aurp_global.glock);*/ ! 203: aurp_global.tunnel = 0; ! 204: aurp_global.event = 0; ! 205: soclose(so); ! 206: *err = ESHUTDOWN; ! 207: return -1; ! 208: } ! 209: ! 210: ! 211: ! 212: /* ! 213: * Set up the nominal uio structure - ! 214: * give it no iov's, point off to non-existant user space, ! 215: * but make sure the 'resid' count means somehting. ! 216: */ ! 217: ! 218: auio.uio_iov = NULL; ! 219: auio.uio_iovcnt = 0; ! 220: auio.uio_segflg = UIO_SYSSPACE; ! 221: auio.uio_offset = 0; /* XXX */ ! 222: ! 223: /* Keep up an even flow... */ ! 224: for (;;) ! 225: { register int empty = 0; ! 226: ! 227: /* ! 228: * This should be large enough to encompass a full DDP packet plus ! 229: * domain header. ! 230: */ ! 231: #define A_LARGE_SIZE 700 ! 232: #ifdef _AIX ! 233: flags = MSG_NONBLOCK; ! 234: #else ! 235: flags = MSG_DONTWAIT; ! 236: #endif ! 237: auio.uio_resid = A_LARGE_SIZE; ! 238: *err = soreceive(so, &from, &auio, &p_mbuf, 0, &flags); ! 239: dPrintf(D_M_AURP, D_L_WARNING, ! 240: ("aurpd: soreceive returned %d\n", *err)); ! 241: /* soreceive() sets *mp to zero! at start */ ! 242: if (p_mbuf) ! 243: ip_to_atalk(from, p_mbuf); ! 244: else ! 245: break; ! 246: } ! 247: } ! 248: ! 249: return -1; ! 250: } ! 251: ! 252: /* ! 253: * Wakeup the sleeping giant - we've put a message on his queue(s). ! 254: * The arg indicates what queue has been updated. ! 255: */ ! 256: void aurp_wakeup(register caddr_t p, int state) ! 257: { register int s; ! 258: register int bit; ! 259: ! 260: bit = (int) p; ! 261: ATDISABLE(s, aurp_global.glock); ! 262: aurp_global.event |= bit; ! 263: ATENABLE(s, aurp_global.glock); ! 264: #ifdef _AIX ! 265: e_wakeup(&aurp_global.event_anchor); ! 266: #else ! 267: thread_wakeup(&aurp_global.event_anchor); ! 268: #endif ! 269: } ! 270: ! 271: /* ! 272: * Try to bind to the specified reserved port. ! 273: * Sort of like sobind(), but no suser() check. ! 274: */ ! 275: aurp_bindrp(so) ! 276: register struct socket *so; ! 277: { ! 278: struct sockaddr_in *sin; ! 279: gbuf_t *m; ! 280: u_short i; ! 281: int error; ! 282: struct ucred *savecred; ! 283: ! 284: m = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in)); ! 285: if (m == NULL) { ! 286: dPrintf(D_M_AURP, D_L_ERROR, ! 287: ("aurp_bindrp: couldn't alloc mbuf")); ! 288: return (ENOBUFS); ! 289: } ! 290: ! 291: sin = (struct sockaddr_in *)gbuf_rptr(m); ! 292: sin->sin_family = AF_INET; ! 293: sin->sin_addr.s_addr = htons(aurp_global.src_addr); ! 294: sin->sin_port = htons(aurp_global.udp_port); ! 295: gbuf_len(m) = sizeof(struct sockaddr_in); ! 296: ! 297: #ifdef _AIX ! 298: SOCKET_LOCK(so); ! 299: #else ! 300: sblock(&so->so_rcv, M_WAIT); ! 301: sblock(&so->so_snd, M_WAIT); ! 302: #endif ! 303: so->so_state |= SS_PRIV; ! 304: error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, 0, m, 0); ! 305: #ifdef _AIX ! 306: SOCKET_UNLOCK(so); ! 307: #else ! 308: sbunlock(&so->so_snd); ! 309: sbunlock(&so->so_rcv); ! 310: #endif ! 311: ! 312: (void) gbuf_freeb(m); ! 313: return (error); ! 314: } ! 315: ! 316: /* ! 317: * receive from UDP ! 318: * fp is the 'source address' mbuf; p_mbuf is the data mbuf. ! 319: * Use the source address to find the 'node number' (index of the address), ! 320: * and pass that to the next stage. ! 321: */ ! 322: int ip_to_atalk(register gbuf_t *fp, register gbuf_t *p_mbuf) ! 323: { register aurp_hdr_t *hdr; ! 324: register domain_t *domain; ! 325: unsigned char node; ! 326: register struct sockaddr_in *rem_addr; ! 327: ! 328: rem_addr = (struct sockaddr_in *)gbuf_rptr(fp); ! 329: /* determine the node where the packet came from */ ! 330: for (node=1; node <= dst_addr_cnt; node++) { ! 331: if (aurp_global.dst_addr[node] == *(long *)&rem_addr->sin_addr) ! 332: break; ! 333: } ! 334: if (node > dst_addr_cnt) { ! 335: dPrintf(D_M_AURP, D_L_WARNING, ! 336: ("AURPrecv: invalid node, %d.%x\n", ! 337: rem_addr->sin_port, ! 338: *(long *)&rem_addr->sin_addr)); ! 339: gbuf_freem(fp); ! 340: gbuf_freem(p_mbuf); ! 341: return -1; ! 342: } ! 343: ! 344: /* validate the domain */ ! 345: domain = (domain_t *)gbuf_rptr(p_mbuf); ! 346: if ( (domain->dst_length != IP_LENGTH) || ! 347: (domain->dst_authority != IP_AUTHORITY) || ! 348: (domain->version != AUD_Version) || ! 349: ((domain->type != AUD_Atalk) && (domain->type != AUD_AURP)) ) { ! 350: dPrintf(D_M_AURP, D_L_WARNING, ! 351: ("AURPrecv: invalid domain, %d.%x\n", ! 352: rem_addr->sin_port, ! 353: *(long *)&rem_addr->sin_addr)); ! 354: gbuf_freem(fp); ! 355: gbuf_freem(p_mbuf); ! 356: return -1; ! 357: } ! 358: ! 359: /* Remove domain header */ ! 360: p_mbuf->m_pkthdr.len -= IP_DOMAINSIZE; ! 361: gbuf_rinc(p_mbuf,IP_DOMAINSIZE); ! 362: gbuf_set_type(p_mbuf, MSG_DATA); ! 363: ! 364: /* forward the packet to the local AppleTalk stack */ ! 365: gbuf_freem(fp); ! 366: at_insert(p_mbuf, domain->type, node); ! 367: return 0; ! 368: } ! 369: ! 370: /* ! 371: * send to UDP ! 372: * The real work has been done already. Here, we just cobble together ! 373: * a sockaddr for the destination and call sosend(). ! 374: */ ! 375: void ! 376: atalk_to_ip(register gbuf_t *m) ! 377: { register domain_t *domain; ! 378: int error; ! 379: #ifdef _AIX ! 380: int flags = MSG_NONBLOCK; ! 381: #else ! 382: int flags = MSG_DONTWAIT; ! 383: #endif ! 384: struct sockaddr_in *rem_addr; ! 385: register gbuf_t *mbp; ! 386: ! 387: m->m_type = MT_HEADER; ! 388: m->m_pkthdr.len = gbuf_msgsize(m); ! 389: m->m_pkthdr.rcvif = 0; ! 390: ! 391: /* Cons up a destination sockaddr */ ! 392: if ((mbp = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in))) == NULL) ! 393: { ! 394: #ifdef _AIX ! 395: (void)fetch_and_add((atomic_p)&aurp_global.no_mbufs, 1); ! 396: #endif ! 397: gbuf_freem(m); ! 398: return; ! 399: } ! 400: ! 401: rem_addr = (struct sockaddr_in *)gbuf_rptr(mbp); ! 402: bzero((char *)rem_addr, sizeof(rem_addr)); ! 403: rem_addr->sin_family = PF_INET; ! 404: rem_addr->sin_port = aurp_global.udp_port; ! 405: gbuf_len(mbp) = sizeof (struct sockaddr_in); ! 406: domain = (domain_t *)gbuf_rptr(m); ! 407: *(long *)&rem_addr->sin_addr = domain->dst_address; ! 408: ! 409: #ifdef _AIX ! 410: (void)fetch_and_add((atomic_p)&aurp_global.running, 1); ! 411: #endif ! 412: if (aurp_global.shutdown) { ! 413: gbuf_freem(m); ! 414: gbuf_freeb(mbp); ! 415: #ifdef _AIX ! 416: (void)fetch_and_add((atomic_p)&aurp_global.running, -1); ! 417: #endif ! 418: return; ! 419: } ! 420: error = sosend(aurp_global.tunnel, mbp, NULL, m, NULL, flags); ! 421: if (error) ! 422: { /*log error*/ ! 423: dPrintf(D_M_AURP, D_L_ERROR, ("AURP: sosend error (%d)\n", ! 424: error)); ! 425: } ! 426: ! 427: gbuf_freeb(mbp); ! 428: #ifdef _AIX ! 429: (void)fetch_and_add((atomic_p)&aurp_global.running, -1); ! 430: #endif ! 431: return; ! 432: } ! 433: ! 434:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.