--- embedaddon/miniupnpd/natpmp.c 2012/02/21 23:16:02 1.1.1.1 +++ embedaddon/miniupnpd/natpmp.c 2012/05/29 12:55:57 1.1.1.2 @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.1.1.1 2012/02/21 23:16:02 misho Exp $ */ +/* $Id: natpmp.c,v 1.1.1.2 2012/05/29 12:55:57 misho Exp $ */ /* MiniUPnP project * (c) 2007-2010 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -39,7 +39,6 @@ int OpenAndConfNATPMPSocket(in_addr_t addr) natpmp_addr.sin_port = htons(NATPMP_PORT); //natpmp_addr.sin_addr.s_addr = INADDR_ANY; natpmp_addr.sin_addr.s_addr = addr; - //natpmp_addr.sin_addr.s_addr = inet_addr("192.168.0.1"); if(bind(snatpmp, (struct sockaddr *)&natpmp_addr, sizeof(natpmp_addr)) < 0) { syslog(LOG_ERR, "bind(natpmp): %m"); @@ -53,9 +52,10 @@ int OpenAndConfNATPMPSocket(in_addr_t addr) int OpenAndConfNATPMPSockets(int * sockets) { int i, j; - for(i=0; ilist.le_next, i++) { - sockets[i] = OpenAndConfNATPMPSocket(lan_addr[i].addr.s_addr); + sockets[i] = OpenAndConfNATPMPSocket(lan_addr->addr.s_addr); if(sockets[i] < 0) { for(j=0; jlist.le_next) { + if( (senderaddr & lan_addr->mask.s_addr) + == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) { + memcpy(resp+8, &lan_addr->ext_ip_addr, + sizeof(lan_addr->ext_ip_addr)); break; } } @@ -138,7 +137,9 @@ void ProcessIncomingNATPMPPacket(int s) memset(resp, 0, sizeof(resp)); resplen = 8; resp[1] = 128 + req[1]; /* response OPCODE is request OPCODE + 128 */ - /* setting response TIME STAMP */ + /* setting response TIME STAMP : + * time elapsed since its port mapping table was initialized on + * startup or reset for any other reason */ *((uint32_t *)(resp+4)) = htonl(time(NULL) - startup_time); if(req[0] > 0) { /* invalid version */ @@ -161,6 +162,8 @@ void ProcessIncomingNATPMPPacket(int s) int proto; char iaddr_old[16]; unsigned short iport_old; + unsigned int timestamp; + iport = ntohs(*((uint16_t *)(req+4))); eport = ntohs(*((uint16_t *)(req+6))); lifetime = ntohl(*((uint32_t *)(req+8))); @@ -185,18 +188,20 @@ void ProcessIncomingNATPMPPacket(int s) while(get_redirect_rule_by_index(index, 0, &eport2, iaddr2, sizeof(iaddr2), &iport2, &proto2, - desc, sizeof(desc), 0, 0) >= 0) { + desc, sizeof(desc), + 0, 0, ×tamp, 0, 0) >= 0) { syslog(LOG_DEBUG, "%d %d %hu->'%s':%hu '%s'", index, proto2, eport2, iaddr2, iport2, desc); if(0 == strcmp(iaddr2, senderaddrstr) - && 0 == memcmp(desc, "NAT-PMP ", 8)) { + && 0 == memcmp(desc, "NAT-PMP", 7)) { r = _upnp_delete_redir(eport2, proto2); /* TODO : check return value */ if(r<0) { syslog(LOG_ERR, "failed to remove port mapping"); index++; } else { - syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed", proto2==IPPROTO_TCP?"TCP":"UDP", eport2); + syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed", + proto2==IPPROTO_TCP?"TCP":"UDP", eport2); } } else { index++; @@ -209,7 +214,8 @@ void ProcessIncomingNATPMPPacket(int s) r = _upnp_delete_redir(eport, proto); /*syslog(LOG_DEBUG, "%hu %d r=%d", eport, proto, r);*/ if(r<0) { - syslog(LOG_ERR, "Failed to remove NAT-PMP mapping eport %hu, protocol %s", eport, (proto==IPPROTO_TCP)?"TCP":"UDP"); + syslog(LOG_ERR, "Failed to remove NAT-PMP mapping eport %hu, protocol %s", + eport, (proto==IPPROTO_TCP)?"TCP":"UDP"); resp[3] = 2; /* Not Authorized/Refused */ } } @@ -220,12 +226,14 @@ void ProcessIncomingNATPMPPacket(int s) } else do { r = get_redirect_rule(ext_if_name, eport, proto, iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0); + &iport_old, 0, 0, 0, 0, + ×tamp, 0, 0); if(r==0) { if(strcmp(senderaddrstr, iaddr_old)==0 && iport==iport_old) { /* redirection allready existing */ - syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old); + syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old); /* remove and then add again */ if(_upnp_delete_redir(eport, proto) < 0) { syslog(LOG_ERR, "failed to remove port mapping"); @@ -238,27 +246,36 @@ void ProcessIncomingNATPMPPacket(int s) } { /* do the redirection */ char desc[64]; - unsigned timestamp = (unsigned)(time(NULL) - startup_time) +#if 0 + timestamp = (unsigned)(time(NULL) - startup_time) + lifetime; snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); +#else + timestamp = time(NULL) + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", + eport, (proto==IPPROTO_TCP)?"tcp":"udp"); +#endif /* TODO : check return code */ - if(upnp_redirect_internal(eport, senderaddrstr, - iport, proto, desc) < 0) { + if(upnp_redirect_internal(NULL, eport, senderaddrstr, + iport, proto, desc, + timestamp) < 0) { syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); resp[3] = 3; /* Failure */ +#if 0 } else if( !nextnatpmptoclean_eport || timestamp < nextnatpmptoclean_timestamp) { nextnatpmptoclean_timestamp = timestamp; nextnatpmptoclean_eport = eport; nextnatpmptoclean_proto = proto; +#endif } break; } } while(r==0); *((uint16_t *)(resp+8)) = htons(iport); /* private port */ *((uint16_t *)(resp+10)) = htons(eport); /* public port */ - *((uint32_t *)(resp+12)) = htonl(lifetime); + *((uint32_t *)(resp+12)) = htonl(lifetime); /* Port Mapping lifetime */ } resplen = 16; break; @@ -275,6 +292,7 @@ void ProcessIncomingNATPMPPacket(int s) } } +#if 0 /* iterate through the redirection list to find those who came * from NAT-PMP and select the first to expire */ int ScanNATPMPforExpiration() @@ -289,7 +307,7 @@ int ScanNATPMPforExpiration() for(i = 0; ; i++) { r = get_redirect_rule_by_index(i, 0, &eport, 0, 0, &iport, &proto, desc, sizeof(desc), - 0, 0); + ×tamp, 0, 0); if(r<0) break; if(sscanf(desc, "NAT-PMP %u", ×tamp) == 1) { @@ -315,7 +333,7 @@ int CleanExpiredNATPMP() if(get_redirect_rule(ext_if_name, nextnatpmptoclean_eport, nextnatpmptoclean_proto, 0, 0, - &iport, desc, sizeof(desc), 0, 0) < 0) + &iport, desc, sizeof(desc), ×tamp, 0, 0) < 0) return ScanNATPMPforExpiration(); /* check desc - this is important since we keep expiration time as part * of the desc. @@ -333,6 +351,7 @@ int CleanExpiredNATPMP() nextnatpmptoclean_proto==IPPROTO_TCP?"TCP":"UDP"); return ScanNATPMPforExpiration(); } +#endif /* SendNATPMPPublicAddressChangeNotification() * should be called when the public IP address changed */ @@ -342,10 +361,13 @@ void SendNATPMPPublicAddressChangeNotification(int * s unsigned char notif[12]; int j, n; - notif[0] = 0; - notif[1] = 128; - notif[2] = 0; - notif[3] = 0; + notif[0] = 0; /* vers */ + notif[1] = 128; /* OP code */ + notif[2] = 0; /* result code */ + notif[3] = 0; /* result code */ + /* seconds since "start of epoch" : + * time elapsed since the port mapping table was initialized on + * startup or reset for any other reason */ *((uint32_t *)(notif+4)) = htonl(time(NULL) - startup_time); #ifndef MULTIPLE_EXTERNAL_IP FillPublicAddressResponse(notif, 0); @@ -358,7 +380,6 @@ void SendNATPMPPublicAddressChangeNotification(int * s #endif memset(&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; - sockname.sin_port = htons(NATPMP_PORT); sockname.sin_addr.s_addr = inet_addr(NATPMP_NOTIF_ADDR); for(j=0; jlist.le_next; + FillPublicAddressResponse(notif, lan_addr->addr.s_addr); + } #endif + /* Port to use in 2006 version of the NAT-PMP specification */ + sockname.sin_port = htons(NATPMP_PORT); + n = sendto(sockets[j], notif, 12, 0, + (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); + if(n < 0) + { + syslog(LOG_ERR, "%s: sendto(s_udp=%d): %m", + "SendNATPMPPublicAddressChangeNotification", sockets[j]); + return; + } + /* Port to use in 2008 version of the NAT-PMP specification */ + sockname.sin_port = htons(NATPMP_NOTIF_PORT); n = sendto(sockets[j], notif, 12, 0, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); if(n < 0)