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 <string.h> 00052 00053 #include <sys/heap.h> 00054 #include <sys/socket.h> 00055 #include <sys/sock_var.h> 00056 #include <sys/types.h> 00057 #include <pro/wins.h> 00058 #include <netinet/in.h> 00059 #ifdef NUTDEBUG 00060 #include <stdio.h> 00061 #endif 00062 00063 extern int toupper(int); 00064 /* ********************************************************* */ 00065 00070 00071 typedef struct { 00072 u_short id; 00073 u_short flags; 00074 u_short quests; 00075 u_short answers; 00076 u_short authrr; 00077 u_short addrr; 00078 u_char namelen; 00079 u_char name[33]; 00080 u_short type; 00081 u_short class; /* end of request */ 00082 u_long ttl; 00083 u_short len_rep; 00084 u_char node_flags; 00085 u_char node_type; 00086 u_long ip_addr; /* end of answer */ 00087 } WINSHEADER; 00088 00089 00090 /* ********************************************************* */ 00091 /* name : netbios label (15 chars max), ipaddr : network ordered IP address bytes */ 00092 int NutWinsNameQuery(char * name, u_long ipaddr) 00093 { 00094 WINSHEADER *pkt = NULL; 00095 u_char *encoded = NULL; 00096 UDPSOCKET *sock; 00097 u_long raddr; 00098 u_short rport; 00099 u_char car; 00100 int i, j; 00101 if (strlen(name) > 15) 00102 return -1; 00103 if (((pkt = NutHeapAllocClear(sizeof(WINSHEADER))) == NULL) || /* */ 00104 ((encoded = NutHeapAllocClear(33)) == NULL) || /* */ 00105 ((sock = NutUdpCreateSocket(137)) == 0) /* NETBIOS UDP port */ 00106 ) { 00107 if (pkt != NULL) 00108 NutHeapFree(pkt); 00109 if (encoded != NULL) 00110 NutHeapFree(encoded); 00111 return -1; 00112 } 00113 j = 0; 00114 for (i = 0; i < 16; i++) { /* label 'compression' */ 00115 car = toupper(i < strlen(name) ? name[i] : ' '); 00116 if (i == 15) 00117 car = 0; 00118 encoded[j] = (car >> 4) + 'A'; 00119 encoded[j + 1] = (car & 0xf) + 'A'; 00120 j += 2; 00121 } 00122 encoded[j] = 0; 00123 /* printf("local compressed name=\n%s \n", encoded); */ 00124 for (;;) { /* infinite loop / Netbios deamon */ 00125 NutUdpReceiveFrom(sock, &raddr, &rport, pkt, sizeof(WINSHEADER), 0); 00126 /* RFC1002 Name Query Request verification */ 00127 if (((ntohs(pkt->flags) & 0xf800) != 0) || /* */ 00128 (ntohs(pkt->quests) != 1) || /* */ 00129 (pkt->namelen != 0x20) || /* */ 00130 (ntohs(pkt->type) != 32) || /* */ 00131 (ntohs(pkt->class) != 1) || /* */ 00132 (strcmp((char *)pkt->name, (char *)encoded))) 00133 continue; /* bad request, try again */ 00134 /* printf("Name=%s recognized\r\n", name); */ 00135 /* build RFC1002 Positive Name Query Response */ 00136 pkt->flags = htons(0x8580); /* Response flags */ 00137 pkt->answers = htons(1); 00138 pkt->ttl = htonl((u_long) 60); /* 60 seconds validity */ 00139 pkt->len_rep = htons(6); 00140 pkt->node_flags = pkt->node_type = pkt->quests = 0; /* B-type node, etc... */ 00141 pkt->ip_addr = ipaddr; /* Returned IP Address, end of answer */ 00142 NutUdpSendTo(sock, raddr, 137, pkt, sizeof(WINSHEADER)); /* send to netbios port */ 00143 memset(pkt, 0, sizeof(WINSHEADER)); 00144 } 00145 } 00146