Nut/OS  4.10.3
API Reference
wins.c
Go to the documentation of this file.
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