📄 udp_usrreq.c
字号:
* Calculate data length and get a mbuf * for UDP and IP headers. */ for (m = m0; m; m = m->m_next) len += m->m_len; MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(m0); return (ENOBUFS); } /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ m->m_off = MMAXOFF - sizeof (struct udpiphdr); m->m_len = sizeof (struct udpiphdr); m->m_next = m0; ui = mtod(m, struct udpiphdr *); ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; ui->ui_ulen = ui->ui_len; /* * Stuff checksum and output datagram. */ ui->ui_sum = 0; if (udpcksum) { if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) ui->ui_sum = -1; } ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ((struct ip *)ui)->ip_ttl = udp_ttl; UDPSTAT(udps_total++); UDPSTAT(udps_outdatagrams++); return (ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), inp->inp_socket));}/* CJ - increased sendspace from 2K, recvspace from 4K */int udp_sendspace = 9000; /* really max datagram size */int udp_recvspace = 9000;/*ARGSUSED*/udp_usrreq(so, req, m, nam, rights) struct socket *so; int req; struct mbuf *m, *nam, *rights;{ struct inpcb *inp = sotoinpcb(so); int error = 0; struct socket *so_tmp; /* SMP */ struct socket *so_addr = NULL; /* SMP */ int status; /* SMP */ struct inpcb *inp_tmp = NULL; /* SMP */ struct inpcb *head = NULL; /* SMP */ /* * SMP: Socket lock set coming in all cases save SENSE. * Up to splnet coming in. */ if (req == PRU_CONTROL) return (in_control(so, (int)m, (caddr_t)nam, (struct ifnet *)rights)); if (rights && rights->m_len) { error = EINVAL; goto release; } if (inp == NULL && req != PRU_ATTACH) { error = EINVAL; goto release; } switch (req) { case PRU_ATTACH: if (inp != NULL) { error = EINVAL; break; } if (smp){ so->ref = 15; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; error = in_pcballoc(so, &udb); smp_unlock(&lk_udb); }else error = in_pcballoc(so, &udb); if (error) break; error = soreserve(so, udp_sendspace, udp_recvspace); if (error) break;#ifdef XTI so->so_xticb.xti_tpinfo = &xti_udpinfo;#endif XTI break; case PRU_DETACH: if (inp == NULL) { error = ENOTCONN; break; } if (smp){ so->ref = 16; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; in_pcbdetach(inp); smp_unlock(&lk_udb); }else in_pcbdetach(inp); break; case PRU_BIND: if (smp){ so->ref = 17; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; error = in_pcbbind(inp, nam); smp_unlock(&lk_udb); }else error = in_pcbbind(inp, nam); break; case PRU_LISTEN: error = EOPNOTSUPP; break; case PRU_CONNECT: if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; break; } if (smp){ so->ref = 18; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; error = in_pcbconnect(inp, nam); smp_unlock(&lk_udb); }else error = in_pcbconnect(inp, nam); if (error == 0) soisconnected(so); break; case PRU_CONNECT2: error = EOPNOTSUPP; break; case PRU_ACCEPT: error = EOPNOTSUPP; break; case PRU_DISCONNECT: if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; break; } if (smp){ so->ref = 19; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; in_pcbdisconnect(inp); smp_unlock(&lk_udb); }else in_pcbdisconnect(inp); so->so_state &= ~SS_ISCONNECTED; /* XXX */ break; case PRU_SHUTDOWN: socantsendmore(so); break; case PRU_SEND: { struct in_addr laddr; if (nam) { laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; break; } /* * Must block input while temporarily connected. */ if (smp){ so->ref = 20; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; error = in_pcbconnect(inp, nam); smp_unlock(&lk_udb); }else error = in_pcbconnect(inp, nam); if (error) { break; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; break; } } error = udp_output(inp, m); m = NULL; if (nam) { if (smp){ so->ref = 21; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; in_pcbdisconnect(inp); smp_unlock(&lk_udb); }else in_pcbdisconnect(inp); inp->inp_laddr = laddr; } } break; case PRU_ABORT: soisdisconnected(so); if (smp){ so->ref = 22; smp_unlock(&so->lk_socket); smp_lock(&lk_udb, LK_RETRY); smp_lock(&so->lk_socket, LK_RETRY); so->ref = 0; in_pcbdetach(inp); smp_unlock(&lk_udb); }else in_pcbdetach(inp); break; case PRU_SOCKADDR: in_setsockaddr(inp, nam); break; case PRU_PEERADDR: in_setpeeraddr(inp, nam); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ return (0); case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: error = EOPNOTSUPP; break; case PRU_RCVD: case PRU_RCVOOB: return (EOPNOTSUPP); /* do not free mbuf's */ default: error = EOPNOTSUPP; }release: if (m != NULL) m_freem(m); return (error);}#ifdef XTIudp_ctloutput(op, so, level, optname, mp) int op; struct socket *so; int level, optname; struct mbuf **mp;{ int error = 0; struct inpcb *inp = sotoinpcb(so); register struct mbuf *m = 0; if (level != IPPROTO_UDP) return (ip_ctloutput(op, so, level, optname, mp)); switch (op) { case PRCO_XTIMAPSTATE: so->so_xticb.xti_states = udp_to_xtistate(so); break; case PRCO_XTIMAPINFO: so->so_xticb.xti_tpinfo = &xti_udpinfo; /* info is per provider */ break; case PRCO_XTIUNBIND: xtiin_pcbunbind(so->so_pcb); break; case PRCO_SETOPT: m = *mp; switch (optname) { default: error = EINVAL; break; }; break; case PRCO_GETOPT: { int tmp_status; *mp = m = m_get(M_WAIT, MT_SOOPTS); m->m_len = sizeof(int); switch (optname) { default: error = EINVAL; break; }; break; } }; if(m) (void) m_free(m); return (error);}/* * KEY * --- * so - socket pointer * inp - internet control block pointer * fd - file desciptor * * STATE MINIMUM MAPPING * ---------- ----------------------------- * T_UNINIT (getsock(fd) == 0)) * T_UNBND (getsock(fd) > 0) * T_IDLE (inp->inp_lport || inp->inp_fport) */udp_to_xtistate(so) struct socket *so;{ int status; int default_state; struct inpcb *inp; /* * determine what state we are in */ /* * we are already past T_UNINIT state, because * if we were a bogus descriptor or a non-socket descriptor we * would have been caught. */ default_state = T_UNBND; if (so) inp = (struct inpcb *) so->so_pcb; if (inp) if (inp->inp_lport || inp->inp_fport) { default_state = T_IDLE; } else { return(default_state); } else return(default_state); return(default_state);}#endif XTI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -