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