00001 00002 /* 00003 * Copyright (C) 2004 by Jean Pierre Gauthier. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 3. Neither the name of the copyright holders nor the names of 00015 * contributors may be used to endorse or promote products derived 00016 * from this software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY <YOUR NAME> AND CONTRIBUTORS 00019 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <YOUR NAME> 00022 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00023 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00024 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00025 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00027 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00028 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00029 * SUCH DAMAGE. 00030 */ 00031 00032 /* ********************************************************* */ 00033 /* 00034 Netbios WINS (RFC 1002) Name Query. 00035 Only Query Request Client Routine sending/Positive Name Query Response receiving 00036 are implemented. 00037 When the Netbios Name Query request UDP datagram is on the ethernet network, asking 00038 "Who is 'name'?", NutWinsNameQuery answers with the specified 'ipaddr' Ethernut IP address. 00039 Answer to Microsoft Windows/Internet Explorer calls by "http://name" command line 00040 (and even directly "name" as command line if "name" is not a shared folder). 00041 00042 Launch for example : 00043 THREAD(wins_deamon, arg) 00044 { 00045 NutWinsNameQuery ( "myboard", inet_addr(MYIP) ) ; 00046 } 00047 */ 00048 /* ********************************************************* */ 00049 00050 #include <cfg/os.h> 00051 #include <stdlib.h> 00052 #include <string.h> 00053 00054 #include <sys/heap.h> 00055 #include <sys/socket.h> 00056 #include <sys/sock_var.h> 00057 #include <sys/types.h> 00058 #include <pro/wins.h> 00059 #include <netinet/in.h> 00060 #ifdef NUTDEBUG 00061 #include <stdio.h> 00062 #endif 00063 00064 extern int toupper(int); 00065 /* ********************************************************* */ 00066 00071 00072 typedef struct { 00073 uint16_t id; 00074 uint16_t flags; 00075 uint16_t quests; 00076 uint16_t answers; 00077 uint16_t authrr; 00078 uint16_t addrr; 00079 uint8_t namelen; 00080 uint8_t name[33]; 00081 uint16_t type; 00082 uint16_t class; /* end of request */ 00083 uint32_t ttl; 00084 uint16_t len_rep; 00085 uint8_t node_flags; 00086 uint8_t node_type; 00087 uint32_t ip_addr; /* end of answer */ 00088 } WINSHEADER; 00089 00090 00091 /* ********************************************************* */ 00092 /* name : netbios label (15 chars max), ipaddr : network ordered IP address bytes */ 00093 int NutWinsNameQuery(char * name, uint32_t ipaddr) 00094 { 00095 WINSHEADER *pkt = NULL; 00096 uint8_t *encoded = NULL; 00097 UDPSOCKET *sock; 00098 uint32_t raddr; 00099 uint16_t rport; 00100 uint8_t car; 00101 int i, j; 00102 if (strlen(name) > 15) 00103 return -1; 00104 if (((pkt = calloc(1, sizeof(WINSHEADER))) == NULL) || /* */ 00105 ((encoded = calloc(33, 1)) == NULL) || /* */ 00106 ((sock = NutUdpCreateSocket(137)) == 0) /* NETBIOS UDP port */ 00107 ) { 00108 if (pkt != NULL) 00109 free(pkt); 00110 if (encoded != NULL) 00111 free(encoded); 00112 return -1; 00113 } 00114 j = 0; 00115 for (i = 0; i < 16; i++) { /* label 'compression' */ 00116 car = toupper(i < strlen(name) ? name[i] : ' '); 00117 if (i == 15) 00118 car = 0; 00119 encoded[j] = (car >> 4) + 'A'; 00120 encoded[j + 1] = (car & 0xf) + 'A'; 00121 j += 2; 00122 } 00123 encoded[j] = 0; 00124 /* printf("local compressed name=\n%s \n", encoded); */ 00125 for (;;) { /* infinite loop / Netbios deamon */ 00126 NutUdpReceiveFrom(sock, &raddr, &rport, pkt, sizeof(WINSHEADER), 0); 00127 /* RFC1002 Name Query Request verification */ 00128 if (((ntohs(pkt->flags) & 0xf800) != 0) || /* */ 00129 (ntohs(pkt->quests) != 1) || /* */ 00130 (pkt->namelen != 0x20) || /* */ 00131 (ntohs(pkt->type) != 32) || /* */ 00132 (ntohs(pkt->class) != 1) || /* */ 00133 (strcmp((char *)pkt->name, (char *)encoded))) 00134 continue; /* bad request, try again */ 00135 /* printf("Name=%s recognized\r\n", name); */ 00136 /* build RFC1002 Positive Name Query Response */ 00137 pkt->flags = htons(0x8580); /* Response flags */ 00138 pkt->answers = htons(1); 00139 pkt->ttl = htonl((uint32_t) 60); /* 60 seconds validity */ 00140 pkt->len_rep = htons(6); 00141 pkt->node_flags = pkt->node_type = pkt->quests = 0; /* B-type node, etc... */ 00142 pkt->ip_addr = ipaddr; /* Returned IP Address, end of answer */ 00143 NutUdpSendTo(sock, raddr, 137, pkt, sizeof(WINSHEADER)); /* send to netbios port */ 00144 memset(pkt, 0, sizeof(WINSHEADER)); 00145 } 00146 } 00147