1 /* raw_imp.c 4.5 82/02/16 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/socket.h" 6 #include "../h/protosw.h" 7 #include "../h/socketvar.h" 8 #include "../net/in.h" 9 #include "../net/in_systm.h" 10 #include "../net/if.h" 11 #include "../net/if_imp.h" 12 #include "../net/raw_cb.h" 13 #include "/usr/include/errno.h" 14 15 /* 16 * Raw interface to IMP. 17 */ 18 19 /*ARGSUSED*/ 20 rimp_ctlinput(m) 21 struct mbuf *m; 22 { 23 COUNT(RIMP_CTLINPUT); 24 } 25 26 /* 27 * Generate IMP leader and pass packet to impoutput. 28 * The user must create a skeletal leader in order to 29 * communicate message type, message subtype, etc. 30 * We fill in holes where needed and verify parameters 31 * supplied by user. 32 */ 33 rimp_output(m, so) 34 register struct mbuf *m; 35 struct socket *so; 36 { 37 struct mbuf *n; 38 int len; 39 register struct imp_leader *ip; 40 register struct sockaddr_in *sin; 41 register struct rawcb *rp = sotorawcb(so); 42 struct ifnet *ifp; 43 struct control_leader *cp; 44 45 COUNT(RIMP_OUTPUT); 46 /* 47 * Verify user has supplied necessary space 48 * for the leader and check parameters in it. 49 */ 50 if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) && 51 (m = m_pullup(m, sizeof(struct control_leader))) == 0) 52 return (0); 53 cp = mtod(m, struct control_leader *); 54 if (cp->dl_mtype == IMPTYPE_DATA) 55 if (m->m_len < sizeof(struct imp_leader) && 56 (m = m_pullup(m, sizeof(struct imp_leader))) == 0) 57 return (0); 58 ip = mtod(m, struct imp_leader *); 59 if (ip->il_format != IMP_NFF) 60 goto bad; 61 if (ip->il_link != IMPLINK_IP && 62 (ip->il_link < IMPLINK_LOWEXPER || ip->il_link > IMPLINK_HIGHEXPER)) 63 goto bad; 64 65 /* 66 * Fill in IMP leader -- impoutput refrains from rebuilding 67 * the leader when it sees the protocol family PF_IMPLINK. 68 * (message size calculated by walking through mbuf's) 69 */ 70 for (len = 0, n = m; n; n = n->m_next) 71 len += n->m_len; 72 ip->il_length = htons(len << 3); 73 sin = (struct sockaddr_in *)&rp->rcb_addr; 74 ip->il_network = sin->sin_addr.s_net; 75 ip->il_host = sin->sin_addr.s_host; 76 ip->il_imp = sin->sin_addr.s_imp; 77 ifp = if_ifonnetof(sin->sin_addr); 78 if (ifp == 0) { 79 ifp = if_gatewayfor(sin->sin_addr); 80 if (ifp == 0) 81 goto bad; 82 } 83 return (impoutput(ifp, m, PF_IMPLINK)); 84 85 bad: 86 m_freem(m); 87 return (0); 88 } 89 90 /* 91 * Intercept operations required to 92 * maintain interface pointer used on output. 93 */ 94 rimp_usrreq(so, req, m, addr) 95 struct socket *so; 96 int req; 97 struct mbuf *m; 98 caddr_t addr; 99 { 100 register struct rawcb *rp = sotorawcb(so); 101 register struct sockaddr_in *sin; 102 register struct ifnet *ifp; 103 104 COUNT(RIMP_USRREQ); 105 if (rp == 0 && req != PRU_ATTACH) 106 return (EINVAL); 107 108 switch (req) { 109 110 /* 111 * Verify address has an interface to go with it. 112 */ 113 case PRU_CONNECT: 114 if (rp->rcb_pcb) 115 return (EISCONN); 116 sin = (struct sockaddr_in *)addr; 117 ifp = if_ifonnetof(sin->sin_addr); 118 if (ifp == 0) { 119 ifp = if_gatewayfor(sin->sin_addr); 120 if (ifp == 0) 121 return (EADDRNOTAVAIL); /* XXX */ 122 } 123 rp->rcb_pcb = (caddr_t)ifp; 124 break; 125 126 case PRU_DISCONNECT: 127 rp->rcb_pcb = 0; 128 break; 129 130 case PRU_CONTROL: 131 return (EOPNOTSUPP); 132 } 133 return (raw_usrreq(so, req, m, addr)); 134 } 135