1: /* 2: * Copyright (c) 1980, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)raw_usrreq.c 7.1 (Berkeley) 6/4/86 7: */ 8: 9: #include "param.h" 10: #include "mbuf.h" 11: #include "domain.h" 12: #include "protosw.h" 13: #include "socket.h" 14: #include "socketvar.h" 15: #include "errno.h" 16: 17: #include "if.h" 18: #include "route.h" 19: #include "netisr.h" 20: #include "raw_cb.h" 21: 22: #include "../vax/mtpr.h" 23: 24: /* 25: * Initialize raw connection block q. 26: */ 27: raw_init() 28: { 29: 30: rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 31: rawintrq.ifq_maxlen = IFQ_MAXLEN; 32: } 33: 34: /* 35: * Raw protocol interface. 36: */ 37: raw_input(m0, proto, src, dst) 38: struct mbuf *m0; 39: struct sockproto *proto; 40: struct sockaddr *src, *dst; 41: { 42: register struct mbuf *m; 43: struct raw_header *rh; 44: int s; 45: 46: /* 47: * Rip off an mbuf for a generic header. 48: */ 49: m = m_get(M_DONTWAIT, MT_HEADER); 50: if (m == 0) { 51: m_freem(m0); 52: return; 53: } 54: m->m_next = m0; 55: m->m_len = sizeof(struct raw_header); 56: rh = mtod(m, struct raw_header *); 57: rh->raw_dst = *dst; 58: rh->raw_src = *src; 59: rh->raw_proto = *proto; 60: 61: /* 62: * Header now contains enough info to decide 63: * which socket to place packet in (if any). 64: * Queue it up for the raw protocol process 65: * running at software interrupt level. 66: */ 67: s = splimp(); 68: if (IF_QFULL(&rawintrq)) 69: m_freem(m); 70: else 71: IF_ENQUEUE(&rawintrq, m); 72: splx(s); 73: schednetisr(NETISR_RAW); 74: } 75: 76: /* 77: * Raw protocol input routine. Process packets entered 78: * into the queue at interrupt time. Find the socket 79: * associated with the packet(s) and move them over. If 80: * nothing exists for this packet, drop it. 81: */ 82: rawintr() 83: { 84: int s; 85: struct mbuf *m; 86: register struct rawcb *rp; 87: register struct raw_header *rh; 88: struct socket *last; 89: 90: next: 91: s = splimp(); 92: IF_DEQUEUE(&rawintrq, m); 93: splx(s); 94: if (m == 0) 95: return; 96: rh = mtod(m, struct raw_header *); 97: last = 0; 98: for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 99: if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) 100: continue; 101: if (rp->rcb_proto.sp_protocol && 102: rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol) 103: continue; 104: /* 105: * We assume the lower level routines have 106: * placed the address in a canonical format 107: * suitable for a structure comparison. 108: */ 109: #define equal(a1, a2) \ 110: (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 111: if ((rp->rcb_flags & RAW_LADDR) && 112: !equal(rp->rcb_laddr, rh->raw_dst)) 113: continue; 114: if ((rp->rcb_flags & RAW_FADDR) && 115: !equal(rp->rcb_faddr, rh->raw_src)) 116: continue; 117: if (last) { 118: struct mbuf *n; 119: if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { 120: if (sbappendaddr(&last->so_rcv, &rh->raw_src, 121: n, (struct mbuf *)0) == 0) 122: /* should notify about lost packet */ 123: m_freem(n); 124: else 125: sorwakeup(last); 126: } 127: } 128: last = rp->rcb_socket; 129: } 130: if (last) { 131: if (sbappendaddr(&last->so_rcv, &rh->raw_src, 132: m->m_next, (struct mbuf *)0) == 0) 133: m_freem(m->m_next); 134: else 135: sorwakeup(last); 136: (void) m_free(m); /* header */ 137: } else 138: m_freem(m); 139: goto next; 140: } 141: 142: /*ARGSUSED*/ 143: raw_ctlinput(cmd, arg) 144: int cmd; 145: struct sockaddr *arg; 146: { 147: 148: if (cmd < 0 || cmd > PRC_NCMDS) 149: return; 150: /* INCOMPLETE */ 151: } 152: 153: /*ARGSUSED*/ 154: raw_usrreq(so, req, m, nam, rights) 155: struct socket *so; 156: int req; 157: struct mbuf *m, *nam, *rights; 158: { 159: register struct rawcb *rp = sotorawcb(so); 160: register int error = 0; 161: 162: if (req == PRU_CONTROL) 163: return (EOPNOTSUPP); 164: if (rights && rights->m_len) { 165: error = EOPNOTSUPP; 166: goto release; 167: } 168: if (rp == 0 && req != PRU_ATTACH) { 169: error = EINVAL; 170: goto release; 171: } 172: switch (req) { 173: 174: /* 175: * Allocate a raw control block and fill in the 176: * necessary info to allow packets to be routed to 177: * the appropriate raw interface routine. 178: */ 179: case PRU_ATTACH: 180: if ((so->so_state & SS_PRIV) == 0) { 181: error = EACCES; 182: break; 183: } 184: if (rp) { 185: error = EINVAL; 186: break; 187: } 188: error = raw_attach(so, (int)nam); 189: break; 190: 191: /* 192: * Destroy state just before socket deallocation. 193: * Flush data or not depending on the options. 194: */ 195: case PRU_DETACH: 196: if (rp == 0) { 197: error = ENOTCONN; 198: break; 199: } 200: raw_detach(rp); 201: break; 202: 203: /* 204: * If a socket isn't bound to a single address, 205: * the raw input routine will hand it anything 206: * within that protocol family (assuming there's 207: * nothing else around it should go to). 208: */ 209: case PRU_CONNECT: 210: if (rp->rcb_flags & RAW_FADDR) { 211: error = EISCONN; 212: break; 213: } 214: raw_connaddr(rp, nam); 215: soisconnected(so); 216: break; 217: 218: case PRU_CONNECT2: 219: error = EOPNOTSUPP; 220: goto release; 221: 222: case PRU_BIND: 223: if (rp->rcb_flags & RAW_LADDR) { 224: error = EINVAL; /* XXX */ 225: break; 226: } 227: error = raw_bind(so, nam); 228: break; 229: 230: case PRU_DISCONNECT: 231: if ((rp->rcb_flags & RAW_FADDR) == 0) { 232: error = ENOTCONN; 233: break; 234: } 235: raw_disconnect(rp); 236: soisdisconnected(so); 237: break; 238: 239: /* 240: * Mark the connection as being incapable of further input. 241: */ 242: case PRU_SHUTDOWN: 243: socantsendmore(so); 244: break; 245: 246: /* 247: * Ship a packet out. The appropriate raw output 248: * routine handles any massaging necessary. 249: */ 250: case PRU_SEND: 251: if (nam) { 252: if (rp->rcb_flags & RAW_FADDR) { 253: error = EISCONN; 254: break; 255: } 256: raw_connaddr(rp, nam); 257: } else if ((rp->rcb_flags & RAW_FADDR) == 0) { 258: error = ENOTCONN; 259: break; 260: } 261: error = (*so->so_proto->pr_output)(m, so); 262: m = NULL; 263: if (nam) 264: rp->rcb_flags &= ~RAW_FADDR; 265: break; 266: 267: case PRU_ABORT: 268: raw_disconnect(rp); 269: sofree(so); 270: soisdisconnected(so); 271: break; 272: 273: case PRU_SENSE: 274: /* 275: * stat: don't bother with a blocksize. 276: */ 277: return (0); 278: 279: /* 280: * Not supported. 281: */ 282: case PRU_RCVOOB: 283: case PRU_RCVD: 284: return(EOPNOTSUPP); 285: 286: case PRU_LISTEN: 287: case PRU_ACCEPT: 288: case PRU_SENDOOB: 289: error = EOPNOTSUPP; 290: break; 291: 292: case PRU_SOCKADDR: 293: bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), 294: sizeof (struct sockaddr)); 295: nam->m_len = sizeof (struct sockaddr); 296: break; 297: 298: case PRU_PEERADDR: 299: bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), 300: sizeof (struct sockaddr)); 301: nam->m_len = sizeof (struct sockaddr); 302: break; 303: 304: default: 305: panic("raw_usrreq"); 306: } 307: release: 308: if (m != NULL) 309: m_freem(m); 310: return (error); 311: }