Diff for /qemu/slirp/udp.c between versions 1.1.1.7 and 1.1.1.8

version 1.1.1.7, 2018/04/24 17:25:49 version 1.1.1.8, 2018/04/24 17:41:09
Line 42 Line 42
 #include "ip_icmp.h"  #include "ip_icmp.h"
   
 static u_int8_t udp_tos(struct socket *so);  static u_int8_t udp_tos(struct socket *so);
 static void udp_emu(struct socket *so, struct mbuf *m);  
   
 void  void
 udp_init(Slirp *slirp)  udp_init(Slirp *slirp)
Line 202  udp_input(register struct mbuf *m, int i Line 201  udp_input(register struct mbuf *m, int i
         /*          /*
          * Now we sendto() the packet.           * Now we sendto() the packet.
          */           */
         if (so->so_emu)  
            udp_emu(so, m);  
   
         if(sosendto(so,m) == -1) {          if(sosendto(so,m) == -1) {
           m->m_len += iphlen;            m->m_len += iphlen;
           m->m_data -= iphlen;            m->m_data -= iphlen;
Line 306  int udp_output(struct socket *so, struct Line 302  int udp_output(struct socket *so, struct
 int  int
 udp_attach(struct socket *so)  udp_attach(struct socket *so)
 {  {
   struct sockaddr_in addr;    if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) {
       so->so_expire = curtime + SO_EXPIRE;
   if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {      insque(so, &so->slirp->udb);
     /*  
      * Here, we bind() the socket.  Although not really needed  
      * (sendto() on an unbound socket will bind it), it's done  
      * here so that emulation of ytalk etc. don't have to do it  
      */  
     addr.sin_family = AF_INET;  
     addr.sin_port = 0;  
     addr.sin_addr.s_addr = INADDR_ANY;  
     if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {  
       int lasterrno=errno;  
       closesocket(so->s);  
       so->s=-1;  
 #ifdef _WIN32  
       WSASetLastError(lasterrno);  
 #else  
       errno=lasterrno;  
 #endif  
     } else {  
       /* success, insert in queue */  
       so->so_expire = curtime + SO_EXPIRE;  
       insque(so, &so->slirp->udb);  
     }  
   }    }
   return(so->s);    return(so->s);
 }  }
Line 344  udp_detach(struct socket *so) Line 318  udp_detach(struct socket *so)
   
 static const struct tos_t udptos[] = {  static const struct tos_t udptos[] = {
         {0, 53, IPTOS_LOWDELAY, 0},                     /* DNS */          {0, 53, IPTOS_LOWDELAY, 0},                     /* DNS */
         {517, 517, IPTOS_LOWDELAY, EMU_TALK},   /* talk */  
         {518, 518, IPTOS_LOWDELAY, EMU_NTALK},  /* ntalk */  
         {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */  
         {0, 0, 0, 0}          {0, 0, 0, 0}
 };  };
   
Line 367  udp_tos(struct socket *so) Line 338  udp_tos(struct socket *so)
         return 0;          return 0;
 }  }
   
 #ifdef EMULATE_TALK  
 #include "talkd.h"  
 #endif  
   
 /*  
  * Here, talk/ytalk/ntalk requests must be emulated  
  */  
 static void  
 udp_emu(struct socket *so, struct mbuf *m)  
 {  
         struct sockaddr_in addr;  
         socklen_t addrlen = sizeof(addr);  
 #ifdef EMULATE_TALK  
         CTL_MSG_OLD *omsg;  
         CTL_MSG *nmsg;  
         char buff[sizeof(CTL_MSG)];  
         u_char type;  
   
 struct talk_request {  
         struct talk_request *next;  
         struct socket *udp_so;  
         struct socket *tcp_so;  
 } *req;  
   
         static struct talk_request *req_tbl = 0;  
   
 #endif  
   
 struct cu_header {  
         uint16_t        d_family;               // destination family  
         uint16_t        d_port;                 // destination port  
         uint32_t        d_addr;                 // destination address  
         uint16_t        s_family;               // source family  
         uint16_t        s_port;                 // source port  
         uint32_t        so_addr;                // source address  
         uint32_t        seqn;                   // sequence number  
         uint16_t        message;                // message  
         uint16_t        data_type;              // data type  
         uint16_t        pkt_len;                // packet length  
 } *cu_head;  
   
         switch(so->so_emu) {  
   
 #ifdef EMULATE_TALK  
          case EMU_TALK:  
          case EMU_NTALK:  
                 /*  
                  * Talk emulation. We always change the ctl_addr to get  
                  * some answers from the daemon. When an ANNOUNCE comes,  
                  * we send LEAVE_INVITE to the local daemons. Also when a  
                  * DELETE comes, we send copies to the local daemons.  
                  */  
                 if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)  
                         return;  
   
 #define IS_OLD  (so->so_emu == EMU_TALK)  
   
 #define COPY_MSG(dest, src) { dest->type = src->type; \  
                               dest->id_num = src->id_num; \  
                               dest->pid = src->pid; \  
                               dest->addr = src->addr; \  
                               dest->ctl_addr = src->ctl_addr; \  
                               memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \  
                               memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \  
                               memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); }  
   
 #define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)  
 /* old_sockaddr to sockaddr_in */  
   
   
                 if (IS_OLD) {           /* old talk */  
                         omsg = mtod(m, CTL_MSG_OLD*);  
                         nmsg = (CTL_MSG *) buff;  
                         type = omsg->type;  
                         OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;  
                         OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;  
                         pstrcpy(omsg->l_name, NAME_SIZE_OLD, getlogin());  
                 } else {                /* new talk */  
                         omsg = (CTL_MSG_OLD *) buff;  
                         nmsg = mtod(m, CTL_MSG *);  
                         type = nmsg->type;  
                         OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;  
                         OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;  
                         pstrcpy(nmsg->l_name, NAME_SIZE_OLD, getlogin());  
                 }  
   
                 if (type == LOOK_UP)  
                         return;         /* for LOOK_UP this is enough */  
   
                 if (IS_OLD) {           /* make a copy of the message */  
                         COPY_MSG(nmsg, omsg);  
                         nmsg->vers = 1;  
                         nmsg->answer = 0;  
                 } else  
                         COPY_MSG(omsg, nmsg);  
   
                 /*  
                  * If if is an ANNOUNCE message, we go through the  
                  * request table to see if a tcp port has already  
                  * been redirected for this socket. If not, we solisten()  
                  * a new socket and add this entry to the table.  
                  * The port number of the tcp socket and our IP  
                  * are put to the addr field of the message structures.  
                  * Then a LEAVE_INVITE is sent to both local daemon  
                  * ports, 517 and 518. This is why we have two copies  
                  * of the message, one in old talk and one in new talk  
                  * format.  
                  */  
   
                 if (type == ANNOUNCE) {  
                         int s;  
                         u_short temp_port;  
   
                         for(req = req_tbl; req; req = req->next)  
                                 if (so == req->udp_so)  
                                         break;          /* found it */  
   
                         if (!req) {     /* no entry for so, create new */  
                                 req = (struct talk_request *)  
                                         malloc(sizeof(struct talk_request));  
                                 req->udp_so = so;  
                                 req->tcp_so = solisten(0,  
                                         OTOSIN(omsg, addr)->sin_addr.s_addr,  
                                         OTOSIN(omsg, addr)->sin_port,  
                                         SS_FACCEPTONCE);  
                                 req->next = req_tbl;  
                                 req_tbl = req;  
                         }  
   
                         /* replace port number in addr field */  
                         addrlen = sizeof(addr);  
                         getsockname(req->tcp_so->s,  
                                         (struct sockaddr *) &addr,  
                                         &addrlen);  
                         OTOSIN(omsg, addr)->sin_port = addr.sin_port;  
                         OTOSIN(omsg, addr)->sin_addr = our_addr;  
                         OTOSIN(nmsg, addr)->sin_port = addr.sin_port;  
                         OTOSIN(nmsg, addr)->sin_addr = our_addr;  
   
                         /* send LEAVE_INVITEs */  
                         temp_port = OTOSIN(omsg, ctl_addr)->sin_port;  
                         OTOSIN(omsg, ctl_addr)->sin_port = 0;  
                         OTOSIN(nmsg, ctl_addr)->sin_port = 0;  
                         omsg->type = nmsg->type = LEAVE_INVITE;  
   
                         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
                         addr.sin_addr = our_addr;  
                         addr.sin_family = AF_INET;  
                         addr.sin_port = htons(517);  
                         sendto(s, (char *)omsg, sizeof(*omsg), 0,  
                                 (struct sockaddr *)&addr, sizeof(addr));  
                         addr.sin_port = htons(518);  
                         sendto(s, (char *)nmsg, sizeof(*nmsg), 0,  
                                 (struct sockaddr *) &addr, sizeof(addr));  
                         closesocket(s) ;  
   
                         omsg->type = nmsg->type = ANNOUNCE;  
                         OTOSIN(omsg, ctl_addr)->sin_port = temp_port;  
                         OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;  
                 }  
   
                 /*  
                  * If it is a DELETE message, we send a copy to the  
                  * local daemons. Then we delete the entry corresponding  
                  * to our socket from the request table.  
                  */  
   
                 if (type == DELETE) {  
                         struct talk_request *temp_req, *req_next;  
                         int s;  
                         u_short temp_port;  
   
                         temp_port = OTOSIN(omsg, ctl_addr)->sin_port;  
                         OTOSIN(omsg, ctl_addr)->sin_port = 0;  
                         OTOSIN(nmsg, ctl_addr)->sin_port = 0;  
   
                         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);  
                         addr.sin_addr = our_addr;  
                         addr.sin_family = AF_INET;  
                         addr.sin_port = htons(517);  
                         sendto(s, (char *)omsg, sizeof(*omsg), 0,  
                                 (struct sockaddr *)&addr, sizeof(addr));  
                         addr.sin_port = htons(518);  
                         sendto(s, (char *)nmsg, sizeof(*nmsg), 0,  
                                 (struct sockaddr *)&addr, sizeof(addr));  
                         closesocket(s);  
   
                         OTOSIN(omsg, ctl_addr)->sin_port = temp_port;  
                         OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;  
   
                         /* delete table entry */  
                         if (so == req_tbl->udp_so) {  
                                 temp_req = req_tbl;  
                                 req_tbl = req_tbl->next;  
                                 free(temp_req);  
                         } else {  
                                 temp_req = req_tbl;  
                                 for(req = req_tbl->next; req; req = req_next) {  
                                         req_next = req->next;  
                                         if (so == req->udp_so) {  
                                                 temp_req->next = req_next;  
                                                 free(req);  
                                                 break;  
                                         } else {  
                                                 temp_req = req;  
                                         }  
                                 }  
                         }  
                 }  
   
                 return;  
 #endif  
   
         case EMU_CUSEEME:  
   
                 /*  
                  * Cu-SeeMe emulation.  
                  * Hopefully the packet is more that 16 bytes long. We don't  
                  * do any other tests, just replace the address and port  
                  * fields.  
                  */  
                 if (m->m_len >= sizeof (*cu_head)) {  
                         if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)  
                                 return;  
                         cu_head = mtod(m, struct cu_header *);  
                         cu_head->s_port = addr.sin_port;  
                         cu_head->so_addr = our_addr.s_addr;  
                 }  
   
                 return;  
         }  
 }  
   
 struct socket *  struct socket *
 udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,  udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
            u_int lport, int flags)             u_int lport, int flags)
Line 612  udp_listen(Slirp *slirp, u_int32_t haddr Line 350  udp_listen(Slirp *slirp, u_int32_t haddr
         if (!so) {          if (!so) {
             return NULL;              return NULL;
         }          }
         so->s = socket(AF_INET,SOCK_DGRAM,0);          so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
         so->so_expire = curtime + SO_EXPIRE;          so->so_expire = curtime + SO_EXPIRE;
         insque(so, &slirp->udb);          insque(so, &slirp->udb);
   

Removed from v.1.1.1.7  
changed lines
  Added in v.1.1.1.8


unix.superglobalmegacorp.com