|
|
1.1 ! root 1: /* ! 2: * udp device driver. ! 3: */ ! 4: ! 5: #include "sys/param.h" ! 6: #include "sys/stream.h" ! 7: #include "sys/conf.h" ! 8: #include "sys/inet/in.h" ! 9: #include "sys/inet/ip.h" ! 10: #include "sys/inet/ip_var.h" ! 11: #include "sys/inet/udp.h" ! 12: #include "sys/inet/udp_var.h" ! 13: #include "sys/inet/udp_user.h" ! 14: ! 15: int udpprintfs; ! 16: long udpdopen(); ! 17: int udpdclose(), udpdput(); ! 18: int udpdosrv(); ! 19: int udpdisrv(); ! 20: static struct qinit udpdrinit = { noput, udpdisrv, udpdopen, udpdclose, 8*1024, 64 }; ! 21: static struct qinit udpdwinit = { udpdput, udpdosrv, udpdopen, udpdclose, ! 22: UDP_BODY_LIMIT, 64 }; ! 23: struct streamtab udpdinfo = { &udpdrinit, &udpdwinit }; ! 24: ! 25: struct cdevsw udpcdev = cstrinit(&udpdinfo); ! 26: ! 27: extern int udpcnt; /* for netstat */ ! 28: extern struct udp udpconn[]; ! 29: ! 30: in_addr udpbaddst; ! 31: ! 32: long ! 33: udpdopen(q, dev) ! 34: register struct queue *q; ! 35: dev_t dev; ! 36: { ! 37: register struct udp *udp; ! 38: ! 39: dev = minor(dev); ! 40: if(dev >= udpcnt) ! 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 = NULL; ! 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: ! 70: switch(bp->type){ ! 71: case M_IOCTL: ! 72: bp->type = M_IOCNAK; ! 73: bp->wptr = bp->rptr; ! 74: qreply(q, bp); ! 75: return; ! 76: case M_DATA: ! 77: putq(q, bp); ! 78: if (bp->class&S_DELIM) ! 79: qenable(q); ! 80: return; ! 81: default: ! 82: freeb(bp); ! 83: return; ! 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: if (bp->type != M_DATA) ! 96: panic("udpdosrv"); ! 97: bp->next = NULL; ! 98: if (udp->head == NULL) ! 99: udp->head = bp; ! 100: else ! 101: udp->tail->next = bp; ! 102: udp->tail = bp; ! 103: if ((bp->class & S_DELIM) == 0) ! 104: continue; ! 105: /* ! 106: * have entire datagram ! 107: */ ! 108: bp->class &=~ S_DELIM; ! 109: if (udp->flags & UDP_INIT) ! 110: udpduser(udp->head, udp); ! 111: else { ! 112: if ((udp->flags & UDP_CONNECTED) == 0 ! 113: && udpdaddr(udp) == 0) ! 114: continue; /* couldn't get an addr */ ! 115: udp_output(udp->head, udp); ! 116: } ! 117: udp->head = udp->tail = NULL; ! 118: } ! 119: } ! 120: ! 121: /* ! 122: * extract address from an outbound datagram ! 123: * return 0 if can't find one ! 124: * -- if return 0, have freed bad message and cleared udp->head ! 125: */ ! 126: udpdaddr(udp) ! 127: register struct udp *udp; ! 128: { ! 129: register struct udpaddr *uap; ! 130: ! 131: /* get destination */ ! 132: if((udp->head = bp_pullup(udp->head, sizeof(struct udpaddr))) == NULL) ! 133: return(0); ! 134: uap = (struct udpaddr *)udp->head->rptr; ! 135: udp->dst = uap->host; ! 136: udp->dport = uap->port; ! 137: udp->head->rptr += sizeof(struct udpaddr); ! 138: ! 139: /* host address for datagrams depends on route */ ! 140: if ((udp->flags & UDP_CONNECTED) == 0) { ! 141: udp->src = ip_hoston(udp->dst); ! 142: if(udp->src == 0) { ! 143: udpbaddst = udp->dst; ! 144: bp_free(udp->head); ! 145: udp->head = NULL; ! 146: return(0); ! 147: } ! 148: } ! 149: return(1); ! 150: } ! 151: ! 152: udpdisrv(q) ! 153: register struct queue *q; ! 154: { ! 155: register struct block *bp; ! 156: ! 157: while((q->next->flag & QFULL)==0){ ! 158: bp = getq(q); ! 159: if(bp == 0) ! 160: break; ! 161: (*q->next->qinfo->putp)(q->next, bp); ! 162: } ! 163: } ! 164: ! 165: udpdrint(bp, ui) ! 166: register struct block *bp; ! 167: struct udpiphdr *ui; ! 168: { ! 169: register struct block *bp1; ! 170: register struct queue *q; ! 171: register struct udp *udp; ! 172: register struct udpaddr *uap; ! 173: register struct udp *udpend; ! 174: int ps = spl6(); ! 175: ! 176: /* find the udp port */ ! 177: udpend = &udpconn[udpcnt]; ! 178: for (udp = udpconn; udp < udpend; ++udp) { ! 179: if (udp->rq == 0) ! 180: continue; ! 181: if (udp->sport != ui->ui_dport) ! 182: continue; ! 183: if (udp->flags & UDP_LISTEN) ! 184: break; ! 185: if ((udp->flags & UDP_CONNECTED) == 0) ! 186: break; ! 187: if (udp->dport == ui->ui_sport && udp->dst == ui->ui_src) ! 188: break; ! 189: } ! 190: ! 191: if (udp >= udpend) { ! 192: if(udpprintfs) ! 193: printf("no udpconn: %d\n", ui->ui_dport); ! 194: udpstat.udps_badport++; ! 195: bp_free(bp); ! 196: splx(ps); ! 197: return; ! 198: } ! 199: if (udp->flags & UDP_LISTEN) { ! 200: udp->dport = ui->ui_sport; ! 201: udp->dst = ui->ui_src; ! 202: if (udp->src == 0) { ! 203: /* use host name connecting end called us */ ! 204: udp->src = ui->ui_dst; ! 205: } ! 206: udp->flags |= UDP_CONNECTED; ! 207: udp->flags &= ~UDP_LISTEN; ! 208: udpreply(udp); ! 209: } ! 210: splx(ps); ! 211: ! 212: if((q = udp->rq) == NULL) { ! 213: printf("udpdrint but no read queue\n"); ! 214: bp_free(bp); ! 215: return; ! 216: } ! 217: if(q->flag & QFULL) { ! 218: if(udpprintfs) ! 219: printf("udpq: %x.%d %x.%d\n", ui->ui_src, ui->ui_sport, ! 220: ui->ui_dst, ui->ui_dport); ! 221: udpstat.udps_inqfull++; ! 222: bp_free(bp); ! 223: return; ! 224: } ! 225: if ((udp->flags & UDP_CONNECTED) == 0) { ! 226: /* if not acting as a connected protocol, pass user source addr */ ! 227: bp1 = allocb(sizeof(struct udpaddr)); ! 228: if (bp1 == NULL) { ! 229: printf("udpdrint: out of blocks\n"); ! 230: bp_free(bp); ! 231: return; ! 232: } ! 233: bp1->wptr += sizeof(struct udpaddr); ! 234: uap = (struct udpaddr *)bp1->rptr; ! 235: uap->host = ui->ui_src; ! 236: uap->port = ui->ui_sport; ! 237: putq(q, bp1); ! 238: } ! 239: while(bp){ ! 240: bp1 = bp->next; ! 241: if (bp1==NULL) ! 242: bp->class |= S_DELIM; ! 243: putq(q, bp); ! 244: bp = bp1; ! 245: } ! 246: qenable(q); ! 247: } ! 248: ! 249: /* ! 250: * first write on this device: ! 251: * data is a command from the user ! 252: */ ! 253: udpduser(bp, udp) ! 254: register struct block *bp; ! 255: register struct udp *udp; ! 256: { ! 257: register struct udpuser *uu; ! 258: ! 259: if ((bp = bp_pullup(bp, sizeof(struct udpuser))) == 0) { ! 260: printf("udpuser short\n"); ! 261: bp_free(bp); ! 262: return; ! 263: } ! 264: uu = (struct udpuser *)bp->rptr; ! 265: switch(uu->cmd){ ! 266: case UDPC_DATAGRAM: ! 267: if (udpbind(udp, uu->sport)) ! 268: goto bad; ! 269: udp->flags &= ~UDP_INIT; ! 270: udpreply(udp); ! 271: break; ! 272: case UDPC_CONNECT: ! 273: if (udpbind(udp, uu->sport)) ! 274: goto bad; ! 275: udp->dport = uu->dport; ! 276: udp->dst = uu->dst; ! 277: udp->flags |= UDP_CONNECTED; ! 278: udp->flags &= ~UDP_INIT; ! 279: udpreply(udp); ! 280: /* pick a local address related to the destination */ ! 281: udp->src = ip_hoston(udp->dst); ! 282: if(udp->src == 0) ! 283: goto bad; ! 284: break; ! 285: case UDPC_LISTEN: ! 286: if (udpbind(udp, uu->sport)) ! 287: goto bad; ! 288: udp->flags |= UDP_LISTEN; ! 289: udp->flags &= ~UDP_INIT; ! 290: break; ! 291: default: ! 292: bad: putctl(udp->rq->next, M_HANGUP); ! 293: return; ! 294: } ! 295: bp_free(bp); ! 296: } ! 297: ! 298: udpreply(udp) ! 299: register struct udp *udp; ! 300: { ! 301: register struct queue *q; ! 302: struct udpreply ur; ! 303: ! 304: ur.reply = UDPR_OK; ! 305: ur.dport = udp->dport; ! 306: ur.dst = udp->dst; ! 307: ur.udpdev = udp - udpconn; ! 308: ! 309: q = udp->rq; ! 310: putcpy(q->next, &ur, sizeof(ur)); ! 311: putctld(q->next, M_DATA); ! 312: } ! 313: ! 314: udpbind(udp, port) ! 315: register struct udp *udp; ! 316: register int port; ! 317: { ! 318: register struct udp *udp2; ! 319: static udp_port udpport = 600; ! 320: ! 321: udp->sport = 0; ! 322: if(port){ ! 323: for(udp2 = &udpconn[0]; udp2 < &udpconn[udpcnt]; udp2++){ ! 324: if(udp2->rq == 0) ! 325: continue; ! 326: if(udp2->sport == port) ! 327: return(1); ! 328: } ! 329: udp->sport = port; ! 330: return(0); ! 331: } ! 332: ! 333: /* pick one for him */ ! 334: if(udpport >= 1024) ! 335: udpport = 600; ! 336: port = udpport; ! 337: while(1){ ! 338: if(udpbind(udp, udpport) == 0){ ! 339: udpport++; ! 340: return(0); ! 341: } ! 342: udpport++; ! 343: if(udpport >= 1024) ! 344: udpport = 600; ! 345: if(udpport == port) /* tried them all */ ! 346: break; ! 347: } ! 348: return(1); ! 349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.