|
|
1.1 ! root 1: /* ! 2: * udp device driver. ! 3: */ ! 4: ! 5: #include "udp.h" ! 6: #if NUDP ! 7: #include "../h/param.h" ! 8: #include "../h/systm.h" ! 9: #include "../h/stream.h" ! 10: #include "../h/ioctl.h" ! 11: #include "../h/ttyld.h" ! 12: #include "../h/buf.h" ! 13: #include "../h/conf.h" ! 14: #include "../h/inet/in.h" ! 15: #include "../h/inet/ip.h" ! 16: #include "../h/inet/ip_var.h" ! 17: #include "../h/inet/udp.h" ! 18: #include "../h/inet/udp_var.h" ! 19: #include "../h/inet/udp_user.h" ! 20: ! 21: int nodev(), udpdopen(), udpdclose(), udpdput(); ! 22: int udpdosrv(); ! 23: static struct qinit udpdrinit = { nodev, NULL, udpdopen, udpdclose, 0, 0 }; ! 24: static struct qinit udpdwinit = { udpdput, udpdosrv, udpdopen, udpdclose, ! 25: UDP_BODY_LIMIT, 64 }; ! 26: struct streamtab udpdinfo = { &udpdrinit, &udpdwinit }; ! 27: ! 28: int Nudp = NUDP; /* for netstat */ ! 29: struct udp udpconn[NUDP]; ! 30: ! 31: in_addr udpbaddst; ! 32: ! 33: udpdopen(q, dev) ! 34: register struct queue *q; ! 35: dev_t dev; ! 36: { ! 37: struct udp *udp; ! 38: ! 39: dev = minor(dev); ! 40: if(dev >= NUDP) ! 41: return(0); ! 42: udp = &udpconn[dev]; ! 43: if(q->ptr) ! 44: return(0); ! 45: udp->rq = q; ! 46: udp->flags = UDP_INIT; ! 47: udp->head = udp->tail = 0; ! 48: q->ptr = (caddr_t)udp; ! 49: q->flag |= QDELIM; ! 50: WR(q)->flag |= QBIGB; ! 51: WR(q)->ptr = (caddr_t)udp; ! 52: return(1); ! 53: } ! 54: ! 55: udpdclose(q) ! 56: register struct queue *q; ! 57: { ! 58: struct udp *udp; ! 59: ! 60: udp = (struct udp *)q->ptr; ! 61: udp->rq = (struct queue *)0; ! 62: q->ptr = (caddr_t)0; ! 63: } ! 64: ! 65: udpdput(q, bp) ! 66: register struct queue *q; ! 67: register struct block *bp; ! 68: { ! 69: struct udp *udp; ! 70: int s, x; ! 71: register union stmsg *sp; ! 72: struct foo{ ! 73: u_long dst; ! 74: u_long gate; ! 75: } *foo; ! 76: ! 77: udp = (struct udp *)q->ptr; ! 78: switch(bp->type){ ! 79: case M_IOCTL: ! 80: bp->type = M_IOCNAK; ! 81: bp->wptr = bp->rptr; ! 82: qreply(q, bp); ! 83: return; ! 84: case M_DATA: ! 85: putq(q, bp); ! 86: break; ! 87: case M_DELIM: ! 88: putq(q, bp); ! 89: qenable(q); ! 90: break; ! 91: default: ! 92: freeb(bp); ! 93: break; ! 94: } ! 95: } ! 96: ! 97: udpdosrv(q) ! 98: register struct queue *q; ! 99: { ! 100: register struct block *bp; ! 101: register struct udp *udp; ! 102: ! 103: udp = (struct udp *)q->ptr; ! 104: while(bp = getq(q)){ ! 105: bp->next = 0; ! 106: if(bp->type != M_DATA) { ! 107: freeb(bp); ! 108: if (udp->flags & UDP_INIT) ! 109: udpduser(udp->head, udp); ! 110: else { ! 111: if ((udp->flags & UDP_CONNECTED) == 0) { ! 112: /* get user-supplied destination */ ! 113: if(udpdaddr(udp)) { ! 114: bp_free(udp->head); ! 115: udp->head = udp->tail = NULL; ! 116: return; ! 117: } ! 118: } else if (udp->head == NULL) { ! 119: /* zero length message */ ! 120: udp->head = allocb(0); ! 121: } ! 122: udp_output(udp->head, udp); ! 123: } ! 124: udp->head = udp->tail = NULL; ! 125: } else if(udp->head == 0){ ! 126: udp->head = udp->tail = bp; ! 127: } else { ! 128: udp->tail->next = bp; ! 129: udp->tail = bp; ! 130: } ! 131: } ! 132: } ! 133: ! 134: /* extract address from a message */ ! 135: udpdaddr(udp) ! 136: register struct udp *udp; ! 137: { ! 138: struct udpaddr *uap; ! 139: ! 140: /* get destination */ ! 141: if((udp->head = bp_pullup(udp->head, sizeof(struct udpaddr))) == NULL) ! 142: return(1); ! 143: uap = (struct udpaddr *)udp->head->rptr; ! 144: udp->dst = uap->host; ! 145: udp->dport = uap->port; ! 146: udp->head->rptr += sizeof(struct udpaddr); ! 147: ! 148: /* host address for datagrams depends on route */ ! 149: if ((udp->flags & UDP_CONNECTED) == 0) { ! 150: udp->src = ip_hoston(udp->dst); ! 151: if(udp->src == 0) { ! 152: udpbaddst = udp->dst; ! 153: return(1); ! 154: } ! 155: } ! 156: return(0); ! 157: } ! 158: ! 159: udpdrint(bp, ui) ! 160: register struct block *bp; ! 161: struct udpiphdr *ui; ! 162: { ! 163: register struct block *bp1; ! 164: register struct queue *q; ! 165: register struct udp *udp; ! 166: register struct udpaddr *uap; ! 167: int ps = spl6(); ! 168: ! 169: /* find the udp port */ ! 170: for (udp = udpconn; udp < &udpconn[NUDP]; ++udp) { ! 171: if (udp->rq == 0) ! 172: continue; ! 173: if (udp->sport != ui->ui_dport) ! 174: continue; ! 175: if (udp->flags & UDP_LISTEN) ! 176: break; ! 177: if ((udp->flags & UDP_CONNECTED) == 0) ! 178: break; ! 179: if (udp->dport == ui->ui_sport && udp->dst == ui->ui_src) ! 180: break; ! 181: } ! 182: ! 183: if (udp == &udpconn[NUDP]) { ! 184: bp_free(bp); ! 185: splx(ps); ! 186: return; ! 187: } ! 188: if (udp->flags & UDP_LISTEN) { ! 189: udp->dport = ui->ui_sport; ! 190: udp->dst = ui->ui_src; ! 191: if (udp->src == 0) { ! 192: /* use host name connecting end called us */ ! 193: udp->src = ui->ui_dst; ! 194: } ! 195: udp->flags |= UDP_CONNECTED; ! 196: udp->flags &= ~UDP_LISTEN; ! 197: udpreply(udp); ! 198: } ! 199: splx(ps); ! 200: ! 201: if((q = udp->rq) == NULL) { ! 202: printf("udpdrint but no read queue\n"); ! 203: bp_free(bp); ! 204: return; ! 205: } ! 206: if(q->next->flag & QFULL) { ! 207: bp_free(bp); ! 208: return; ! 209: } ! 210: if ((udp->flags & UDP_CONNECTED) == 0) { ! 211: /* if not acting as a connected protocol, pass user source addr */ ! 212: bp1 = allocb(sizeof(struct udpaddr)); ! 213: if (bp1 == NULL) { ! 214: printf("udprint: out of blocks\n"); ! 215: bp_free(bp); ! 216: return; ! 217: } ! 218: bp1->wptr += sizeof(struct udpaddr); ! 219: uap = (struct udpaddr *)bp1->rptr; ! 220: uap->host = ui->ui_src; ! 221: uap->port = ui->ui_sport; ! 222: putq(q->next, bp1); ! 223: } ! 224: while(bp){ ! 225: bp1 = bp->next; ! 226: putq(q->next, bp); ! 227: bp = bp1; ! 228: } ! 229: putctl(q->next, M_DELIM); ! 230: } ! 231: ! 232: /* ! 233: * imitation udp_usrreq ! 234: */ ! 235: udpduser(bp, udp) ! 236: register struct block *bp; ! 237: register struct udp *udp; ! 238: { ! 239: struct udpuser *uu; ! 240: ! 241: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) { ! 242: printf("udpuser short\n"); ! 243: bp_free(bp); ! 244: return; ! 245: } ! 246: uu = (struct udpuser *)bp->rptr; ! 247: switch(uu->cmd){ ! 248: case UDPC_DATAGRAM: ! 249: if (udpbind(udp, uu->sport)) ! 250: goto bad; ! 251: udp->flags &= ~UDP_INIT; ! 252: udpreply(udp); ! 253: break; ! 254: case UDPC_CONNECT: ! 255: if (udpbind(udp, uu->sport)) ! 256: goto bad; ! 257: udp->dport = uu->dport; ! 258: udp->dst = uu->dst; ! 259: udp->flags |= UDP_CONNECTED; ! 260: udp->flags &= ~UDP_INIT; ! 261: udpreply(udp); ! 262: /* pick a local address related to the destination */ ! 263: udp->src = ip_hoston(udp->dst); ! 264: if(udp->src == 0) ! 265: goto bad; ! 266: break; ! 267: case UDPC_LISTEN: ! 268: if (udpbind(udp, uu->sport)) ! 269: goto bad; ! 270: udp->flags |= UDP_LISTEN; ! 271: udp->flags &= ~UDP_INIT; ! 272: break; ! 273: default: ! 274: bad: putctl(udp->rq->next, M_HANGUP); ! 275: return; ! 276: } ! 277: bp_free(bp); ! 278: } ! 279: ! 280: udpreply(udp) ! 281: register struct udp *udp; ! 282: { ! 283: register struct queue *q; ! 284: struct udpreply ur; ! 285: ! 286: ur.reply = UDPR_OK; ! 287: ur.dport = udp->dport; ! 288: ur.dst = udp->dst; ! 289: ur.udpdev = udp - udpconn; ! 290: ! 291: q = udp->rq; ! 292: putcpy(q->next, &ur, sizeof(ur)); ! 293: putctl(q->next, M_DELIM); ! 294: } ! 295: ! 296: udpbind(udp, port) ! 297: register struct udp *udp; ! 298: register int port; ! 299: { ! 300: register struct udp *udp2; ! 301: static udp_port udpport = 600; ! 302: ! 303: udp->sport = 0; ! 304: if(port){ ! 305: for(udp2 = &udpconn[0]; udp2 < &udpconn[NUDP]; udp2++){ ! 306: if(udp2->rq == 0) ! 307: continue; ! 308: if(udp2->sport == port) ! 309: return(1); ! 310: } ! 311: udp->sport = port; ! 312: return(0); ! 313: } ! 314: ! 315: /* pick one for him */ ! 316: if(udpport >= 1024) ! 317: udpport = 600; ! 318: port = udpport; ! 319: while(1){ ! 320: if(udpbind(udp, udpport) == 0){ ! 321: udpport++; ! 322: return(0); ! 323: } ! 324: udpport++; ! 325: if(udpport >= 1024) ! 326: udpport = 600; ! 327: if(udpport == port) /* tried them all */ ! 328: break; ! 329: } ! 330: return(1); ! 331: } ! 332: ! 333: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.