Browse Source

Initial commit. Not much yet

Julien 'Lta' BALLET 11 years ago
commit
1eb100dc62
12 changed files with 503 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 31 0
      Makefile
  3. 134 0
      dsm.c
  4. 11 0
      include/bdsm.h
  5. 21 0
      include/bdsm/context.h
  6. 36 0
      include/bdsm/netbios_defs.h
  7. 25 0
      include/bdsm/netbios_ns.h
  8. 21 0
      include/bdsm/netbios_utils.h
  9. 40 0
      src/context.c
  10. BIN
      src/nbt_ns.o
  11. 75 0
      src/netbios_ns.c
  12. 106 0
      src/netbios_utils.c

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+pysmb-1.1.8/*
+ref/*
+

+ 31 - 0
Makefile

@@ -0,0 +1,31 @@
+# Makefile for libdsm
+
+CFLAGS      = -g3 -O0 -I include -DBDSM_DEBUG=0
+LDFLAGS     = -levent
+CC          = clang
+
+UTIL				= dsm
+LIB					= libdsm.so
+
+UTIL_SRC		= dsm.c 							\
+							src/netbios_utils.c	\
+							src/netbios_ns.c		\
+							src/context.c
+
+UTIL_OBJS		= $(UTIL_SRC:.c=.o)
+
+all: $(UTIL)
+
+clean:
+	rm -f $(UTIL) $(UTIL_OBJS)
+
+re: clean all
+
+$(UTIL): $(UTIL_OBJS)
+	$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS)
+
+.c.o:
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+
+.PHONY: all clean re

+ 134 - 0
dsm.c

@@ -0,0 +1,134 @@
+// Test file for libevent
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+
+#define NBT_UDP_PORT        138
+#define NBT_TCP_PORT        139
+
+#include "bdsm.h"
+#include "bdsm/netbios_utils.h"
+
+int main(int ac, char **av)
+{
+  struct sockaddr_in  addr;
+  int                 sock;
+  int                 sock_opt = 1;
+
+  netbios_name_t      nb_name;
+  char                test[64];
+  int                 res;
+
+  nb_name = netbios_name_encode("Cerbere", 0, NETBIOS_WORKSTATION);
+  res = netbios_name_decode(nb_name, test, 0);
+
+  printf("Encoded: %s\n", (char *)nb_name + 1);
+  printf("Decoded: %s\n", (char *)test);
+
+  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+  {
+    printf("Unable to create socket: %s\n", strerror(errno));
+    exit(42);
+  }
+
+  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (void *)&sock_opt, sizeof(sock_opt)) < 0)
+  {
+    printf("Unable to set broadcast opt on socket: %s\n", strerror(errno));
+    close(sock);
+    exit(42);
+  }
+
+  sock_opt = 0;
+  if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&sock_opt, sizeof(sock_opt)) < 0)
+  {
+    printf("Unable to set broadcast opt on socket: %s\n", strerror(errno));
+    close(sock);
+    exit(42);
+  }
+
+  addr.sin_family = AF_INET;
+  //addr.sin_port = htons(NBT_UDP_PORT);
+  addr.sin_port = htons(0);
+  addr.sin_addr.s_addr = 0;
+
+  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+  {
+    printf("Unable to bind socket: %s\n", strerror(errno));
+    close(sock);
+    exit(42);
+  }
+
+  // // Let's build a packet;
+  // nbt_ns_packet_t     *packet = malloc(512);
+  // unsigned int        payload_size = 34 + 4;
+  // nbt_encoded_name_t  encoded_name;
+
+  // nbt_encode_name(av[1], strlen(av[1]), encoded_name);
+  // printf("Requested encoded_name = %.32s\n", encoded_name);
+
+  // memset((void *)packet, 0, 512);
+  // packet->trn_id      = rand();
+  // packet->flags       = htons(0x0110);
+  // packet->qd_count    = htons(1);
+  // packet->payload[0]  = 0x20;
+  // memcpy(packet->payload + 1, encoded_name, 33);
+  // packet->payload[34] = 0x00;
+  // packet->payload[35] = 0x20;
+  // packet->payload[36] = 0x00;
+  // packet->payload[37] = 0x01;
+
+
+
+  // struct sockaddr_in  bcast_addr;
+  // ssize_t             sent;
+
+  // inet_aton("255.255.255.255", &(bcast_addr.sin_addr));
+  // bcast_addr.sin_family = AF_INET;
+  // bcast_addr.sin_port   = htons(137);
+
+  // sent = sendto(sock, (void *)packet, sizeof(nbt_ns_packet_t) + payload_size, 0,
+  //               (struct sockaddr *)&bcast_addr, sizeof(struct sockaddr_in));
+
+  // if (sent < 0)
+  // {
+  //   perror("sendto");
+  //   close(sock);
+  //   exit(42);
+  // }
+  // else
+  // {
+  //   printf("Packet emitted ! (%lu bytes)\n", sizeof(nbt_ns_packet_t) + payload_size);
+  // }
+
+  // struct sockaddr_in  recv_addr;
+  // size_t              recv_addr_length;
+  // ssize_t             recv;
+  // char                buffer[512];
+
+  // recv = recvfrom(sock, (void *)buffer, 512, 0, 0, 0);
+
+  // if (recv < 0)
+  // {
+  //   perror("recvfrom");
+  //   close(sock);
+  //   exit(42);
+  // }
+
+  // for(size_t i = 0; i < recv; i++)
+  // {
+  //   printf("%X", buffer[i]);
+  // }
+  // printf("\n");
+
+  // return (0);
+}

+ 11 - 0
include/bdsm.h

@@ -0,0 +1,11 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#ifndef __BDSM_H_
+#define __BDSM_H_
+
+#include "bdsm/context.h"
+
+#endif

+ 21 - 0
include/bdsm/context.h

@@ -0,0 +1,21 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#ifndef __BDSM_CONTEXT_H_
+#define __BDSM_CONTEXT_H_
+
+//#include <event2/event.h>
+
+#include "bdsm/netbios_ns.h"
+
+typedef struct      bdsm_context_s {
+  //struct event_base   *event_base;
+  netbios_ns_t      *ns;
+}                   bdsm_context_t;
+
+bdsm_context_t    *bdsm_context_new();
+void              bdsm_context_close(bdsm_context_t *ctx);
+
+#endif

+ 36 - 0
include/bdsm/netbios_defs.h

@@ -0,0 +1,36 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#ifndef __BDSM_NETBIOS_DEFS_H_
+#define __BDSM_NETBIOS_DEFS_H_
+
+#include <stdint.h>
+
+#define NETBIOS_UDP_PORT      137 // NS Port
+#define NETBIOS_TCP_PORT      138 // Session Port
+
+#define NETBIOS_NAME_LENGTH   15
+
+// Netbios name types
+#define NETBIOS_WORKSTATION   0x00
+#define NETBIOS_MESSENGER     0x03
+#define NETBIOS_FILESERVER    0x20
+#define NETBIOS_DOMAINMASTER  0x1b
+
+typedef struct              netbios_query_s {
+  uint16_t                    rtn_id;     // Transaction ID
+  uint16_t                    flags;      // Various flags
+  uint16_t                    queries;    // Number of queries in this packet
+  uint16_t                    answers;    // Number of answers
+  uint16_t                    ns_count;   // Number of authorities (?)
+  uint16_t                    ar_count;   // Additionnal (??)
+  char                        payload[];
+} __attribute__((packed))   netbios_query_t;
+
+// Crazy encoded level 2 netbios name (null-terminated)
+typedef char  *netbios_name_t;
+
+
+#endif

+ 25 - 0
include/bdsm/netbios_ns.h

@@ -0,0 +1,25 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#ifndef __BDSM_NETBIOS_NS_H_
+#define __BDSM_NETBIOS_NS_H_
+
+#include "bdsm/netbios_defs.h"
+
+#include <sys/socket.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+typedef struct      netbios_ns_s {
+  int                 socket;
+  struct sockaddr_in  addr;
+  uint16_t            last_trn_id;  // Last transaction id used;
+}                   netbios_ns_t;
+
+netbios_ns_t  *netbios_ns_new();
+void          netbios_ns_destroy(netbios_ns_t *ns);
+uint32_t      netbios_ns_resolve(netbios_ns_t *ns, const char *name);
+
+#endif

+ 21 - 0
include/bdsm/netbios_utils.h

@@ -0,0 +1,21 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#ifndef __BDSM_NETBIOS_UTILS_H_
+#define __BDSM_NETBIOS_UTILS_H_
+
+#include "netbios_defs.h"
+
+void  netbios_name_level1_encode(const char *name, char *encoded_name,
+                                 unsigned type);
+void  netbios_name_level1_decode(const char *encoded_name, char *name);
+
+// XXX: domain support is not implemented
+netbios_name_t  netbios_name_encode(const char *name, char *domain,
+                                    unsigned type);
+int             netbios_name_decode(const netbios_name_t encoded_name,
+                                    char *name, char **domain);
+
+#endif

+ 40 - 0
src/context.c

@@ -0,0 +1,40 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "bdsm/context.h"
+
+bdsm_context_t    *bdsm_context_new()
+{
+  bdsm_context_t  *ctx;
+
+  ctx = malloc(sizeof(bdsm_context_t));
+  memset((void *)ctx, 0, sizeof(bdsm_context_t));
+
+  //if (BDSM_DEBUG)
+  //  event_enable_debug_mode();
+
+  //ctx->event_base = event_base_new();
+  if (!(ctx->ns = netbios_ns_new()))
+  {
+    free(ctx);
+    return (0);
+  }
+
+  return (ctx);
+}
+
+void              bdsm_context_close(bdsm_context_t *ctx)
+{
+  if (!ctx)
+    return;
+
+  if (ctx->event_base)
+    event_base_free(ctx->event_base);
+
+  free(ctx);
+}

BIN
src/nbt_ns.o


+ 75 - 0
src/netbios_ns.c

@@ -0,0 +1,75 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "bdsm/netbios_ns.h"
+
+static int    ns_open_socket(netbios_ns_t *ns)
+{
+  int sock_opt;
+
+  if ((ns->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+    goto error;
+
+  sock_opt = 1;
+  if (setsockopt(ns->socket, SOL_SOCKET, SO_BROADCAST,
+      (void *)&sock_opt, sizeof(sock_opt)) < 0)
+    goto error;
+
+  sock_opt = 0;
+  if (setsockopt(ns->socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+      (void *)&sock_opt, sizeof(sock_opt)) < 0)
+    goto error;
+
+  ns->addr.sin_family       = AF_INET;
+  ns->addr.sin_port         = htons(0);
+  ns->addr.sin_addr.s_addr  = 0;
+  if (bind(ns->socket, (struct sockaddr *)&ns->addr, sizeof(ns->addr)) < 0)
+    goto error;
+
+  return (1);
+
+  error:
+    perror("netbios_ns_new, open_socket: ");
+    return (0);
+}
+
+netbios_ns_t  *netbios_ns_new()
+{
+  netbios_ns_t  *ns;
+
+  ns = malloc(sizeof(netbios_ns_t));
+  memset((void *)ns, 0, sizeof(netbios_ns_t));
+
+  if (!ns_open_socket(ns))
+  {
+    netbios_ns_destroy(ns);
+    return (0);
+  }
+
+  ns->last_trn_id = rand();
+
+  return (ns);
+}
+
+void          netbios_ns_destroy(netbios_ns_t *ns)
+{
+  if (!ns)
+    return;
+
+  close(ns->socket);
+  free(ns);
+}
+
+uint32_t      netbios_ns_resolve(netbios_ns_t *ns, const char *name)
+{
+
+}

+ 106 - 0
src/netbios_utils.c

@@ -0,0 +1,106 @@
+// This file is part of libdsm
+// Author: Julien 'Lta' BALLET <contact@lta.io>
+// Copyright VideoLabs 2014
+// License: MIT License
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "bdsm/netbios_utils.h"
+
+static short  nibble_encode(char c)
+{
+  short n1, n2;
+
+  n1 = (toupper(c) >> 4)   + 'A';
+  n2 = (toupper(c) & 0x0F) + 'A';
+
+  return ((n1 << 8) | n2);
+}
+
+static char   nibble_decode(char c1, char c2)
+{
+  return (((c1 - 'A') << 4) + (c2 - 'A'));
+}
+
+
+// name must be null-terminated, it will be truncated if >= 16 chars
+// encoded name must the 33bytes long at least, will be null-terminated
+void  netbios_name_level1_encode(const char *name, char *encoded_name,
+                                 unsigned type)
+{
+  size_t    name_length = strlen(name);
+  char      symbol;
+
+  if (name_length > NETBIOS_NAME_LENGTH)
+    name_length = NETBIOS_NAME_LENGTH;
+
+  for(unsigned int i = 0; i < NETBIOS_NAME_LENGTH; i++)
+  {
+    if (i < name_length)
+    {
+      encoded_name[2 * i]     = nibble_encode(name[i]) >> 8;
+      encoded_name[2 * i + 1] = nibble_encode(name[i]) & 0x00FF;
+    }
+    else
+    {
+      encoded_name[2 * i]     = 'C';
+      encoded_name[2 * i + 1] = 'A';
+    }
+  }
+
+  encoded_name[30] = nibble_encode(type) >> 8;
+  encoded_name[31] = nibble_encode(type) &  0x00FF;
+  encoded_name[32] = '\0';
+}
+
+// encoded_name: 33bytes long
+// name: at least 16bytes long (the string will be null-terminated)
+void  netbios_name_level1_decode(const char *encoded_name, char *name)
+{
+  for (unsigned int i = 0; i < NETBIOS_NAME_LENGTH; i++)
+  {
+    name[i] = nibble_decode(encoded_name[2 * i], encoded_name[2 * i + 1]);
+  }
+  name[NETBIOS_NAME_LENGTH] = 0;
+}
+
+
+netbios_name_t  netbios_name_encode(const char *name, char *domain,
+                                    unsigned type)
+{
+  size_t    encoded_size = 34; // length byte + 32 bytes for encoded name + terminator
+  char      *encoded_name;
+
+  if (!name)
+    return (0);
+
+  encoded_name = malloc(sizeof(encoded_size));
+  encoded_name[0] = 32; // length of the field;
+  netbios_name_level1_encode(name, encoded_name + 1, type);
+
+  return (encoded_name);
+}
+
+int             netbios_name_decode(const netbios_name_t encoded_name,
+                                    char *name, char **domain)
+{
+  size_t  encoded_length;
+
+  if (!encoded_name || !name)
+    return(-1);
+
+  encoded_length =  strlen(encoded_name);
+
+  // XXX Support domain name :p
+  if(encoded_length != 33)
+    return (-1);
+
+  netbios_name_level1_decode(encoded_name + 1, name);
+  name[33] = '\0';
+
+  return (32);
+}
+
+