⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmblib.c

📁 MC Linux/Unix 终端下文件管理器
💻 C
📖 第 1 页 / 共 2 页
字号:
    offset = 12;  }  /* and any resource records */  if (nmb->header.ancount &&       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,			   nmb->header.ancount))    return(False);  if (nmb->header.nscount &&       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,			   nmb->header.nscount))    return(False);    if (nmb->header.arcount &&       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,			   nmb->header.arcount))    return(False);  return(True);}/*******************************************************************  'Copy constructor' for an nmb packet  ******************************************************************/static struct packet_struct *copy_nmb_packet(struct packet_struct *packet){    struct nmb_packet *nmb;  struct nmb_packet *copy_nmb;  struct packet_struct *pkt_copy;  if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)  {    DEBUG(0,("copy_nmb_packet: malloc fail.\n"));    return NULL;  }  /* Structure copy of entire thing. */  *pkt_copy = *packet;  /* Ensure this copy is not locked. */  pkt_copy->locked = False;  /* Ensure this copy has no resource records. */  nmb = &packet->packet.nmb;  copy_nmb = &pkt_copy->packet.nmb;  copy_nmb->answers = NULL;  copy_nmb->nsrecs = NULL;  copy_nmb->additional = NULL;  /* Now copy any resource records. */  if (nmb->answers)  {    if((copy_nmb->answers = (struct res_rec *)                  malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)      goto free_and_exit;    memcpy((char *)copy_nmb->answers, (char *)nmb->answers,            nmb->header.ancount * sizeof(struct res_rec));  }  if (nmb->nsrecs)  {    if((copy_nmb->nsrecs = (struct res_rec *)                  malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)      goto free_and_exit;    memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,            nmb->header.nscount * sizeof(struct res_rec));  }  if (nmb->additional)  {    if((copy_nmb->additional = (struct res_rec *)                  malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)      goto free_and_exit;    memcpy((char *)copy_nmb->additional, (char *)nmb->additional,            nmb->header.arcount * sizeof(struct res_rec));  }  return pkt_copy;free_and_exit:  if(copy_nmb->answers)    free((char *)copy_nmb->answers);  if(copy_nmb->nsrecs)    free((char *)copy_nmb->nsrecs);  if(copy_nmb->additional)    free((char *)copy_nmb->additional);  free((char *)pkt_copy);  DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));  return NULL;}/*******************************************************************  'Copy constructor' for a dgram packet  ******************************************************************/static struct packet_struct *copy_dgram_packet(struct packet_struct *packet){   struct packet_struct *pkt_copy;  if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)  {    DEBUG(0,("copy_dgram_packet: malloc fail.\n"));    return NULL;  }  /* Structure copy of entire thing. */  *pkt_copy = *packet;  /* Ensure this copy is not locked. */  pkt_copy->locked = False;  /* There are no additional pointers in a dgram packet,     we are finished. */  return pkt_copy;}/*******************************************************************  'Copy constructor' for a generic packet  ******************************************************************/struct packet_struct *copy_packet(struct packet_struct *packet){    if(packet->packet_type == NMB_PACKET)    return copy_nmb_packet(packet);  else if (packet->packet_type == DGRAM_PACKET)    return copy_dgram_packet(packet);  return NULL;} /*******************************************************************  free up any resources associated with an nmb packet  ******************************************************************/static void free_nmb_packet(struct nmb_packet *nmb){    if (nmb->answers) free(nmb->answers);  if (nmb->nsrecs) free(nmb->nsrecs);  if (nmb->additional) free(nmb->additional);}/*******************************************************************  free up any resources associated with a dgram packet  ******************************************************************/static void free_dgram_packet(struct dgram_packet *nmb){    /* We have nothing to do for a dgram packet. */}/*******************************************************************  free up any resources associated with a packet  ******************************************************************/void free_packet(struct packet_struct *packet){    if (packet->locked)     return;  if (packet->packet_type == NMB_PACKET)    free_nmb_packet(&packet->packet.nmb);  else if (packet->packet_type == DGRAM_PACKET)    free_dgram_packet(&packet->packet.dgram);  free(packet);}/*******************************************************************  read a packet from a socket and parse it, returning a packet ready  to be used or put on the queue. This assumes a UDP socket  ******************************************************************/struct packet_struct *read_packet(int fd,enum packet_type packet_type){  extern struct in_addr lastip;  extern int lastport;  struct packet_struct *packet;  char buf[MAX_DGRAM_SIZE];  int length;  BOOL ok=False;    length = read_udp_socket(fd,buf,sizeof(buf));  if (length < MIN_DGRAM_SIZE) return(NULL);  packet = (struct packet_struct *)malloc(sizeof(*packet));  if (!packet) return(NULL);  packet->next = NULL;  packet->prev = NULL;  packet->ip = lastip;  packet->port = lastport;  packet->fd = fd;  packet->locked = False;  packet->timestamp = time(NULL);  packet->packet_type = packet_type;  switch (packet_type)     {    case NMB_PACKET:      ok = parse_nmb(buf,length,&packet->packet.nmb);      break;    case DGRAM_PACKET:      ok = parse_dgram(buf,length,&packet->packet.dgram);      break;    }  if (!ok) {    DEBUG(10,("read_packet: discarding packet id = %d\n",                  packet->packet.nmb.header.name_trn_id));    free_packet(packet);    return(NULL);  }  num_good_receives++;  DEBUG(5,("Received a packet of len %d from (%s) port %d\n",	    length, inet_ntoa(packet->ip), packet->port ) );  return(packet);}					 /*******************************************************************  send a udp packet on a already open socket  ******************************************************************/static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port){  BOOL ret;  struct sockaddr_in sock_out;  /* set the address and port */  memset((char *)&sock_out,'\0',sizeof(sock_out));  putip((char *)&sock_out.sin_addr,(char *)&ip);  sock_out.sin_port = htons( port );  sock_out.sin_family = AF_INET;    DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",	      len, inet_ntoa(ip), port ) );	  ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,		sizeof(sock_out)) >= 0);  if (!ret)    DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",	     inet_ntoa(ip),port,strerror(errno)));  if (ret)    num_good_sends++;  return(ret);}/*******************************************************************  build a dgram packet ready for sending  XXXX This currently doesn't handle packets too big for one  datagram. It should split them and use the packet_offset, more and  first flags to handle the fragmentation. Yuck.  ******************************************************************/static int build_dgram(char *buf,struct packet_struct *p){  struct dgram_packet *dgram = &p->packet.dgram;  unsigned char *ubuf = (unsigned char *)buf;  int offset=0;  /* put in the header */  ubuf[0] = dgram->header.msg_type;  ubuf[1] = (((int)dgram->header.flags.node_type)<<2);  if (dgram->header.flags.more) ubuf[1] |= 1;  if (dgram->header.flags.first) ubuf[1] |= 2;  RSSVAL(ubuf,2,dgram->header.dgm_id);  putip(ubuf+4,(char *)&dgram->header.source_ip);  RSSVAL(ubuf,8,dgram->header.source_port);  RSSVAL(ubuf,12,dgram->header.packet_offset);  offset = 14;  if (dgram->header.msg_type == 0x10 ||      dgram->header.msg_type == 0x11 ||      dgram->header.msg_type == 0x12) {          offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);    offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);  }  memcpy(ubuf+offset,dgram->data,dgram->datasize);  offset += dgram->datasize;  /* automatically set the dgm_length */  dgram->header.dgm_length = offset;  RSSVAL(ubuf,10,dgram->header.dgm_length);   return(offset);}/*******************************************************************  build a nmb name *******************************************************************/void make_nmb_name( struct nmb_name *n, const char *name, int type ){	extern pstring global_scope;	memset( (char *)n, '\0', sizeof(struct nmb_name) );	StrnCpy( n->name, name, 15 );	strupper( n->name );	n->name_type = (unsigned int)type & 0xFF;	StrnCpy( n->scope, global_scope, 63 );	strupper( n->scope );}/*******************************************************************  Compare two nmb names  ******************************************************************/BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2){  return ((n1->name_type == n2->name_type) &&         strequal(n1->name ,n2->name ) &&         strequal(n1->scope,n2->scope));}/*******************************************************************  build a nmb packet ready for sending  XXXX this currently relies on not being passed something that expands  to a packet too big for the buffer. Eventually this should be  changed to set the trunc bit so the receiver can request the rest  via tcp (when that becomes supported)  ******************************************************************/static int build_nmb(char *buf,struct packet_struct *p){  struct nmb_packet *nmb = &p->packet.nmb;  unsigned char *ubuf = (unsigned char *)buf;  int offset=0;  /* put in the header */  RSSVAL(ubuf,offset,nmb->header.name_trn_id);  ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;  if (nmb->header.response) ubuf[offset+2] |= (1<<7);  if (nmb->header.nm_flags.authoritative &&       nmb->header.response) ubuf[offset+2] |= 0x4;  if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;  if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;  if (nmb->header.nm_flags.recursion_available &&      nmb->header.response) ubuf[offset+3] |= 0x80;  if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;  ubuf[offset+3] |= (nmb->header.rcode & 0xF);  RSSVAL(ubuf,offset+4,nmb->header.qdcount);  RSSVAL(ubuf,offset+6,nmb->header.ancount);  RSSVAL(ubuf,offset+8,nmb->header.nscount);  RSSVAL(ubuf,offset+10,nmb->header.arcount);    offset += 12;  if (nmb->header.qdcount) {    /* XXXX this doesn't handle a qdcount of > 1 */    offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);    RSSVAL(ubuf,offset,nmb->question.question_type);    RSSVAL(ubuf,offset+2,nmb->question.question_class);    offset += 4;  }  if (nmb->header.ancount)    offset += put_res_rec((char *)ubuf,offset,nmb->answers,			  nmb->header.ancount);  if (nmb->header.nscount)    offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,			  nmb->header.nscount);  /*   * The spec says we must put compressed name pointers   * in the following outgoing packets :   * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,   * NAME_RELEASE_REQUEST.   */  if((nmb->header.response == False) &&     ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||      (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||      (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||      (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||      (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&     (nmb->header.arcount == 1)) {    offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);  } else if (nmb->header.arcount) {    offset += put_res_rec((char *)ubuf,offset,nmb->additional,			  nmb->header.arcount);    }  return(offset);}/*******************************************************************  send a packet_struct  ******************************************************************/BOOL send_packet(struct packet_struct *p){  char buf[1024];  int len=0;  memset(buf,'\0',sizeof(buf));  switch (p->packet_type)     {    case NMB_PACKET:      len = build_nmb(buf,p);      debug_nmb_packet(p);      break;    case DGRAM_PACKET:      len = build_dgram(buf,p);      break;    }  if (!len) return(False);  return(send_udp(p->fd,buf,len,p->ip,p->port));}/****************************************************************************  receive a packet with timeout on a open UDP filedescriptor  The timeout is in milliseconds  ***************************************************************************/struct packet_struct *receive_packet(int fd,enum packet_type type,int t){  fd_set fds;  struct timeval timeout;  FD_ZERO(&fds);  FD_SET(fd,&fds);  timeout.tv_sec = t/1000;  timeout.tv_usec = 1000*(t%1000);  sys_select(fd+1,&fds,&timeout);  if (FD_ISSET(fd,&fds))     return(read_packet(fd,type));  return(NULL);}/****************************************************************************return the number of bits that match between two 4 character buffers  ***************************************************************************/static int matching_bits(uchar *p1, uchar *p2){	int i, j, ret = 0;	for (i=0; i<4; i++) {		if (p1[i] != p2[i]) break;		ret += 8;	}	if (i==4) return ret;	for (j=0; j<8; j++) {		if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;		ret++;	}			return ret;}static uchar sort_ip[4];/****************************************************************************compare two query reply records  ***************************************************************************/static int name_query_comp(uchar *p1, uchar *p2){	return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);}/****************************************************************************sort a set of 6 byte name query response records so that the IPs thathave the most leading bits in common with the specified address come first  ***************************************************************************/void sort_query_replies(char *data, int n, struct in_addr ip){	if (n <= 1) return;	putip(sort_ip, (char *)&ip);	qsort(data, n, 6, QSORT_CAST name_query_comp);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -