home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / RDP / rdp_output.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  10.0 KB  |  396 lines

  1. /**************************************************************************/
  2. /*       Copyright(c) 1987, 1992 by BBN Systems and Technologies,         */
  3. /*         A Division of Bolt Beranek and Newman Inc.                     */
  4. /*                                                                        */
  5. /*       RDP implementation for 4.2/4.3bsd by Craig Partridge             */
  6. /*                                                                        */
  7. /*  Permission to use, copy, modify, distribute, and sell this software   */
  8. /*  and its documentation for any purpose is hereby granted without fee,  */
  9. /*  provided that the above copyright notice and this permission appear   */
  10. /*  in all copies and in supporting documentation, and that the name of   */
  11. /*  Bolt Beranek and Newman Inc.  not be used in advertising or           */
  12. /*  publicity pertaining to distribution of the software without          */
  13. /*  specific, written prior permission. BBN makes no representations      */
  14. /*  about the suitability of this software for any purposes.  It is       */
  15. /*  provided "AS IS" without express or implied warranties.               */
  16. /**************************************************************************/
  17.  
  18. #include "../h/param.h"
  19. #include "../h/dir.h"
  20. #include "../h/user.h"
  21. #include "../h/mbuf.h"
  22. #include "../h/protosw.h"
  23. #include "../h/socket.h"
  24. #include "../h/socketvar.h"
  25. #include "../h/errno.h"
  26.  
  27. #include "../net/if.h"
  28. #include "../net/route.h"
  29.  
  30. #include "../netinet/in.h"
  31. #include "../netinet/in_pcb.h"
  32. #include "../netinet/in_systm.h"
  33. #include "../netinet/ip.h"
  34. #include "../netinet/ip_var.h"
  35. #include "../netinet/ip_icmp.h"
  36.  
  37. #include "../netinet/rdp.h"
  38. #include "../netinet/rdp_var.h"
  39. #include "../netinet/rdp_ip.h"
  40. #include "../netinet/rdp_conf.h"
  41.  
  42. extern u_short rdp_mtu;
  43.  
  44. /**************************************************************************/
  45. /*         send a data packet, if no data then send a NULL segment        */
  46. /**************************************************************************/
  47.  
  48. rdp_send(inp, m0)
  49. struct inpcb *inp;
  50. struct mbuf *m0;
  51. {
  52.     register struct rdpip *ri;
  53.     register struct mbuf *m;
  54.     register u_short dlen;
  55.     register int i;
  56.     register struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  57.     struct rdpque *rq = rp->rp_rq;
  58.     int flags;
  59.     struct socket *so = inp->inp_socket;
  60.     int error = 0;
  61.  
  62.     /* first, find out if we have a place for the packet */
  63.     i = rp->rp_sndnxt - rp->rp_snduna;
  64.  
  65.     /* over running our buffer or remote buffer? */
  66.     if ((i >= R_MAXSND) || (i >= (rp->rp_sndmax << 1)))
  67.     {
  68.     error = ENOBUFS;
  69.     goto drop;
  70.     }
  71.  
  72.     /* exceeding max in flight? */
  73.     if (rp->rp_inflt >= rp->rp_maxinflt)
  74.     panic("rdp_send: inflt");
  75.  
  76.     /* now, find the data length */
  77.     for(dlen=0,m=m0; m != 0; m = m->m_next)
  78.     dlen += m->m_len;
  79.  
  80.     if (dlen > rp->rp_sndbuf)
  81.     {
  82.     error = EMSGSIZE;
  83.     goto drop;
  84.     }
  85.  
  86.     /* grab header and set up */
  87.     MGET(m,M_DONTWAIT,MT_HEADER);
  88.     if (m == 0)
  89.     {
  90.     error = ENOBUFS;
  91.     goto drop;
  92.     }
  93.  
  94.     m->m_len = RI_SIZE;
  95.     m->m_off = MMAXOFF - m->m_len;
  96.     m->m_next = m0;
  97.     bzero(mtod(m,caddr_t),m->m_len);
  98.  
  99.     ri = mtod(m,struct rdpip *);
  100.  
  101.     ri->ri_pr = IPPROTO_RDP;
  102.     ri->ri_ttl = MAXTTL;
  103.  
  104.     ri->ri_src = inp->inp_laddr;
  105.     ri->ri_dst = inp->inp_faddr;
  106.     ri->ri_sport = inp->inp_lport;
  107.     ri->ri_dport = inp->inp_fport;
  108.  
  109.     ri->ri_dlen = ntohs((u_short)dlen);
  110.  
  111.     if (dlen == 0)
  112.     ri->ri_flags = RH_NULL | R_VERSION;
  113.     else
  114.     ri->ri_flags = R_VERSION;
  115.  
  116.     /* RFC: page 34 requires than an ACK always be present in data */
  117.  
  118.     ri->ri_flags |= RH_ACK;
  119.     ri->ri_an = htonl(rp->rp_rcvcur);
  120.  
  121.     ri->ri_sn = htonl(rp->rp_sndnxt);
  122.  
  123.     /* don't swap bytes -- IP does it for IP header */
  124.     ri->ri_len = (u_short)(RI_SIZE+dlen);
  125.     ri->ri_hlen = (R_HDRSIZE >> 1);
  126.  
  127.     /* sum was zeroed by the bzero above */
  128.     m->m_off += sizeof(struct ip);
  129.     m->m_len -= sizeof(struct ip);
  130.     ri->ri_sum = in_cksum(m,(int)dlen + R_HDRSIZE);
  131.     m->m_off -= sizeof(struct ip);
  132.     m->m_len += sizeof(struct ip);
  133.  
  134.     /* now, increment sndnxt and buffer socket level */
  135.     rp->rp_sndnxt++;
  136.     rp->rp_inflt++;
  137.  
  138.     /* statistics */
  139.     rp->rp_datsegs++;
  140.  
  141.     /* if at max inflight or end of buffering, tell socket level to hold it */
  142.     if ((rp->rp_inflt >= rp->rp_maxinflt) || (i == (R_MAXSND-1)) || (i == (rp->rp_sndmax << 1)-1))
  143.     {
  144.     so->so_snd.sb_cc = so->so_snd.sb_hiwat;
  145.     rdp_info.rst_fullwin++;
  146.     }
  147.  
  148.  
  149.     /* stuff packet in queues */
  150.     i += rq->rq_sndbase;
  151.     i %= R_MAXSND;
  152.  
  153.     rq->rq_sndq[i] = m;
  154.     rq->rq_sndtimer[i] = 0;
  155.     rq->rq_retries[i] = 0;
  156.  
  157.     /* activity timer */
  158.     rp->rp_timer = RT_NULLTIME;
  159.  
  160.     error = 0;
  161.  
  162.     /* copy packet */
  163.     if ((m0 = m_copy(m,0,(int)M_COPYALL))==0)
  164.     goto quit;
  165.  
  166.     rdp_info.rst_opackets++;
  167.  
  168.     flags = so->so_state & SS_PRIV;
  169.     return(ip_output(m0,(struct mbuf *)0,&(inp->inp_route),flags));
  170.  
  171. drop:
  172.     if (m0 != 0)
  173.     (void) m_freem(m0);
  174.  
  175. quit:
  176.     return(error);
  177. }
  178.  
  179. /**************************************************************************/
  180. /*                    send an RST segment                                 */
  181. /**************************************************************************/
  182.  
  183. rdp_rst(inp,isack,seq,ack,route)
  184. struct inpcb *inp;
  185. int isack;
  186. u_long seq, ack;
  187. int route;
  188. {
  189.     register struct rdpip *ri;
  190.     register struct mbuf *m;
  191.     int flags;
  192.  
  193.     m = m_getclr(M_DONTWAIT,MT_HEADER);
  194.     if (m == 0)
  195.     return(ENOBUFS);
  196.  
  197.     m->m_len = RI_SIZE;
  198.     m->m_off = MMAXOFF - m->m_len;
  199.     m->m_next = 0;
  200.  
  201.     ri = mtod(m,struct rdpip *);
  202.  
  203.     ri->ri_pr = IPPROTO_RDP;
  204.     ri->ri_ttl = MAXTTL;
  205.  
  206.     ri->ri_src = inp->inp_laddr;
  207.     ri->ri_dst = inp->inp_faddr;
  208.     ri->ri_sport = inp->inp_lport;
  209.     ri->ri_dport = inp->inp_fport;
  210.     ri->ri_flags = RH_RST | R_VERSION;
  211.  
  212.     if (isack)
  213.     {
  214.     /* ack has special meanings -- don't fiddle with EACKs */
  215.     ri->ri_flags |= RH_ACK;
  216.     ri->ri_an = htonl(ack);
  217.     }
  218.  
  219.     ri->ri_sn = htonl(seq);
  220.  
  221.     ri->ri_hlen = (R_HDRSIZE >> 1);
  222.     /* IP worries about byte order */
  223.     ri->ri_len = ((u_short)RI_SIZE);
  224.  
  225.     m->m_off += sizeof(struct ip);
  226.     m->m_len -= sizeof(struct ip);
  227.     ri->ri_sum = 0;
  228.     ri->ri_sum = in_cksum(m,R_HDRSIZE);
  229.     m->m_off -= sizeof(struct ip);
  230.     m->m_len += sizeof(struct ip);
  231.  
  232.     flags = inp->inp_socket->so_state & SS_PRIV;
  233.  
  234.     rdp_info.rst_opackets++;
  235.  
  236.     if (route)
  237.     return(ip_output(m,(struct mbuf *)0,&(inp->inp_route),flags));
  238.  
  239.     return(ip_output(m,(struct mbuf *)0,(struct route *)0,flags));
  240. }
  241.  
  242. /**************************************************************************/
  243. /*             send an ACK segment (with EACKs if supported)              */
  244. /**************************************************************************/
  245.  
  246. rdp_ack(inp,seq,ack)
  247. struct inpcb *inp;
  248. u_long seq, ack;
  249. {
  250.     register struct rdpip *ri;
  251.     register struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  252. #ifdef EACK
  253.     register struct rdpque *rq;
  254.     register int i, j;
  255.     register u_long *lp;
  256.     u_long eack;
  257. #endif
  258.     struct mbuf *m;
  259.     unsigned len;
  260.     int flags;
  261.  
  262.     MGET(m,M_DONTWAIT,MT_HEADER);
  263.     if (m == 0)
  264.     return(ENOBUFS);
  265.  
  266.     m->m_len = len = RI_SIZE;
  267.     /* leave enough space for possible EACKs */
  268.     m->m_off = MMAXOFF - (len + ((rp->rp_rcvhi - rp->rp_rcvcur) << 2));
  269.     m->m_next = 0;
  270.  
  271.     ri = mtod(m,struct rdpip *);
  272.  
  273.     ri->ri_pr = IPPROTO_RDP;
  274.     ri->ri_ttl = MAXTTL;
  275.  
  276.     ri->ri_src = inp->inp_laddr;
  277.     ri->ri_dst = inp->inp_faddr;
  278.     ri->ri_sport = inp->inp_lport;
  279.     ri->ri_dport = inp->inp_fport;
  280.  
  281.     ri->ri_flags = R_VERSION | RH_ACK;
  282.     ri->ri_an = htonl(ack);
  283.  
  284.     ri->ri_sn = htonl(seq);
  285.  
  286. #ifdef EACK
  287.     /* add EACKs and increment len */
  288.     if ((i=(rp->rp_rcvhi - rp->rp_rcvcur)) != 0)
  289.     {
  290.     ri->ri_flags |= RH_EACK;
  291.     lp = (u_long *)(((caddr_t)ri)+len);
  292.  
  293.     rq = rp->rp_rq;
  294.     j = rq->rq_rcvbase;
  295.     eack= rp->rp_rcvcur + 1;
  296.  
  297.     for(; i > 0; i--, eack++)
  298.     {
  299.         if (rq->rq_rcvq[j] != 0)
  300.         {
  301.         *lp++ = eack;
  302.         len += sizeof(*lp);
  303.         }
  304.         if (++j == R_RCVWIN)
  305.         j = 0;
  306.     }
  307.     m->m_len = len;
  308.     }
  309. #endif
  310.  
  311.     ri->ri_len = ((u_short)len);
  312.     len -= sizeof(struct ip);
  313.     ri->ri_hlen = (len >> 1);
  314.     ri->ri_dlen = 0;
  315.  
  316.     m->m_off += sizeof(struct ip);
  317.     m->m_len -= sizeof(struct ip);
  318.     ri->ri_sum = 0;
  319.     ri->ri_sum = in_cksum(m,(int)len);
  320.     m->m_off -= sizeof(struct ip);
  321.     m->m_len += sizeof(struct ip);
  322.  
  323.     rdp_info.rst_opackets++;
  324.  
  325.     flags = inp->inp_socket->so_state & SS_PRIV;
  326.     return(ip_output(m,(struct mbuf *)0,&(inp->inp_route),flags)); 
  327. }
  328.  
  329. /**************************************************************************/
  330. /*                        send SYN segment                                */
  331. /**************************************************************************/
  332.  
  333. rdp_syn(inp,isack,seq,ack)
  334. struct inpcb *inp;
  335. int isack;
  336. u_long seq, ack;
  337. {
  338.     register struct rdpip *ri;
  339.     register struct mbuf *m;
  340.     register struct rdpsyn *rs;
  341.     register int len;
  342.     int flags;
  343.  
  344.     m = m_getclr(M_DONTWAIT,MT_HEADER);
  345.     if (m == 0)
  346.     return(ENOBUFS);
  347.  
  348.     m->m_len = len = RI_SIZE+R_VARSIZE;
  349.     m->m_off = MMAXOFF - len;
  350.     m->m_next = 0;
  351.  
  352.     ri = mtod(m,struct rdpip *);
  353.     m->m_off += RI_SIZE;
  354.     rs = mtod(m,struct rdpsyn *);
  355.     m->m_off -= RI_SIZE;
  356.  
  357.     ri->ri_pr = IPPROTO_RDP;
  358.     ri->ri_ttl = MAXTTL;
  359.  
  360.     ri->ri_src = inp->inp_laddr;
  361.     ri->ri_dst = inp->inp_faddr;
  362.     ri->ri_sport = inp->inp_lport;
  363.     ri->ri_dport = inp->inp_fport;
  364.     ri->ri_flags = RH_SYN | R_VERSION;
  365.  
  366.     if (isack)
  367.     {
  368.     /* ack has special meanings -- don't fiddle with EACKs */
  369.     ri->ri_flags |= RH_ACK;
  370.     ri->ri_an = htonl(ack);
  371.     }
  372.  
  373.     rs->rs_mos = htons((u_short)R_RCVMAX);
  374.     rs->rs_mss = htons(rdp_mtu);
  375.  
  376.     if (inp->inp_socket->so_type != SOCK_RDM)
  377.     rs->rs_ff = RS_SDM;
  378.  
  379.     ri->ri_sn = htonl(seq);
  380.  
  381.     ri->ri_hlen = ((R_HDRSIZE+R_VARSIZE) >> 1);
  382.     ri->ri_len = (u_short)len;
  383.  
  384.     m->m_off += sizeof(struct ip);
  385.     m->m_len -= sizeof(struct ip);
  386.     ri->ri_sum = 0;
  387.     ri->ri_sum = in_cksum(m,len - sizeof(struct ip));
  388.     m->m_off -= sizeof(struct ip);
  389.     m->m_len += sizeof(struct ip);
  390.  
  391.     rdp_info.rst_opackets++;
  392.  
  393.     flags = inp->inp_socket->so_state & SS_PRIV;
  394.     return(ip_output(m,(struct mbuf *)0,&(inp->inp_route),flags));
  395. }
  396.