int reciveping(sred *cabr,unsigned char *tuip,int *tiempopac,int sec,int tamtra) { int tamano; struct timeval start, end; long int ptime=0; gettimeofday(&start, NULL); while( ptime < 100)//ciclo que recibira tramas { tamano = recvfrom(cabr->paquete,tramapingrec,74,0,NULL,0); if(tamano == -1) printf("Error al recibir ping"); else { if(!memcmp(tramapingrec,cabr->mac,6)&&!memcmp(tramapingrec+12,ethertypeping,2)&&!memcmp(tramapingrec+26,tuip,4)&&!memcmp(tramapingrec+30,cabr->ip,4)) { gettimeofday(&end, NULL); ptime =(end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000; ctapac[1]++; tiempopac[intime]=ptime;intime++; printf("\nrespuesta desde ");putip(tuip); printf(": bytes=74 tiempo=%ldms ttl=%d",ptime,tramapingenv[22]); return(1); } } gettimeofday(&end, NULL); ptime =(end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000; } printf("\nrespuesta desde ");putip(tuip); printf(": fallida time=%ldms ttl=%d",ptime,tramapingenv[22]); ctapac[2]++; return(0); }
void putdatos() { printf("\n\t\tpaquete:\t\t\t%d",cabr->paquete); printf("\n\t\tindice:\t\t\t\t%d",cabr->indice); printf("\n\t\tip:\t\t\t\t");putip(cabr->ip); printf("\n\t\tmac:\t\t\t\t");putmac(cabr->mac); printf("\n\t\tmascara:\t\t\t");putip(cabr->mascara); printf("\n\t\tip publica:\t\t\t");putip(cabr->ippu); printf("\n\t\tip puerta enlace:\t\t");putip(cabr->ipenlace); printf("\n\t\tmac puerta enlace\t\t");putmac(cabr->macenlace); }
void process_name_release_request(struct subnet_record *subrec, struct packet_struct *p) { struct nmb_packet *nmb = &p->packet.nmb; struct in_addr owner_ip; struct nmb_name *question = &nmb->question.question_name; unstring qname; BOOL bcast = nmb->header.nm_flags.bcast; uint16 nb_flags = get_nb_flags(nmb->additional->rdata); BOOL group = (nb_flags & NB_GROUP) ? True : False; struct name_record *namerec; int rcode = 0; putip((char *)&owner_ip,&nmb->additional->rdata[2]); if(!bcast) { /* We should only get broadcast name release packets here. Anyone trying to release unicast should be going to a WINS server. If the code gets here, then either we are not a wins server and they sent it anyway, or we are a WINS server and the request was malformed. Either way, log an error here. and send an error reply back. */ DEBUG(0,("process_name_release_request: unicast name release request \ received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); send_name_release_response(FMT_ERR, p); return; }
int resivearp(sred *cabr,unsigned char *tuip,unsigned char *tumac) { struct timeval start, end; double time; gettimeofday(&start, NULL); while(time<2000) { int tam; tam=recvfrom(cabr->paquete,tramaarprec,48,0,NULL,0); if(tam==-1) {perror("\nError al recibir trama");} else { if(!memcmp(tramaarprec+20,codrespuesta,2)&&!memcmp(tramaarprec+0,cabr->mac,6)&&!memcmp(tramaarprec+28,tuip,4)) { memcpy(tumac+0,tramaarprec+6,6); printf("\npidiendo mac ala ip ");putip(tuip);printf(" ..."); printf("su mac es: ");putmac(tumac);printf("\n"); return 0; } } gettimeofday(&end, NULL); time =(end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000.0; } return 1; }
int open_udp_socket(const char *host, int port) { int type = SOCK_DGRAM; struct sockaddr_in sock_out; int res; struct in_addr *addr; addr = interpret_addr2(host); res = socket(PF_INET, type, 0); if (res == -1) { return -1; } memset((char *)&sock_out,'\0',sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); sock_out.sin_port = htons(port); sock_out.sin_family = PF_INET; if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) { close(res); return -1; } return res; }
static void release_name_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { /* a release is *always* considered to be successful when it times out. This doesn't cause problems as if a WINS server doesn't respond and someone else wants the name then the normal WACK/name query from the WINS server will cope */ struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; bool bcast = sent_nmb->header.nm_flags.bcast; struct nmb_name *question_name = &sent_nmb->question.question_name; struct in_addr released_ip; /* Get the ip address we were trying to release. */ putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]); if (!bcast) { /* mark the WINS server temporarily dead */ wins_srv_died(rrec->packet->ip, released_ip); } DEBUG(5,("release_name_timeout_response: success in releasing name %s on subnet %s.\n", nmb_namestr(question_name), subrec->subnet_name)); if (rrec->success_fn) { (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip); } standard_success_release( subrec, rrec->userdata, question_name, released_ip); remove_response_record(subrec, rrec); }
int comprueba(unsigned char *ipin,unsigned char *macin) { sprintf(consulta,"select * from ipmac where ip='%d.%d.%d.%d'",ipin[0],ipin[1],ipin[2],ipin[3]); if (mysql_query(con,consulta)) {fprintf(stderr, "%s\n", mysql_error(con));printf("\n\n\t\t\terror mysql");exit(-1);} res=mysql_use_result(con); while ((row = mysql_fetch_row(res)) != NULL) { sscanf(row[0],"%d.%d.%d.%d",(int*)&ipm[0],(int*)&ipm[1],(int*)&ipm[2],(int*)&ipm[3]); sscanf(row[1],"%x:%x:%x:%x:%x:%x",(unsigned int *)&macm[0],(unsigned int *)&macm[1],(unsigned int *)&macm[2],(unsigned int *)&macm[3],(unsigned int *)&macm[4],(unsigned int *)&macm[5]); if(!memcmp(ipin+0,ipm+0,4)) { if(!memcmp(macin+0,macm+0,6)) { mysql_free_result(res); return 0; } printf("\n\nla mac es incorrecta"); printf("\nip:");putip(ipin);printf("\tmac:");putmac(macin); memcpy(cabr->macbase+0,macm+0,6); //printf("cabr->macbase====");putmac(cabr->macbase); mysql_free_result(res); return 1; } } mysql_free_result(res); return 3; }
static void find_all_domain_master_names_query_success(struct subnet_record *subrec, struct userdata_struct *userdata_in, struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) { /* * We now have a list of all the domain master browsers for all workgroups * that have registered with the WINS server. Now do a node status request * to each one and look for the first 1b name in the reply. This will be * the workgroup name that we will add to the unicast subnet as a 'non-local' * workgroup. */ struct nmb_name nmbname; struct in_addr send_ip; int i; if( DEBUGLVL( 5 ) ) { dbgtext( "find_all_domain_master_names_query_succes:\n" ); dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) ); dbgtext( "IP addresses for Domain Master Browsers.\n" ); } for(i = 0; i < rrec->rdlength / 6; i++) { /* Initiate the node status requests. */ make_nmb_name(&nmbname, "*", 0); putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]); /* * Don't send node status requests to ourself. */ if(ismyip( send_ip )) { if( DEBUGLVL( 5 ) ) { dbgtext( "find_all_domain_master_names_query_succes:\n" ); dbgtext( "Not sending node status to our own IP " ); dbgtext( "%s.\n", inet_ntoa(send_ip) ); } continue; } if( DEBUGLVL( 5 ) ) { dbgtext( "find_all_domain_master_names_query_success:\n" ); dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) ); } node_status( subrec, &nmbname, send_ip, get_domain_master_name_node_status_success, get_domain_master_name_node_status_fail, NULL); } }
static void register_name_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { /* * If we are registering unicast, then NOT getting a response is an * error - we do not have the name. If we are registering broadcast, * then we don't expect to get a response. */ struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; bool bcast = sent_nmb->header.nm_flags.bcast; bool success = False; struct nmb_name *question_name = &sent_nmb->question.question_name; uint16_t nb_flags = 0; int ttl = 0; struct in_addr registered_ip; if (bcast) { if(rrec->num_msgs == 0) { /* Not receiving a message is success for broadcast registration. */ success = True; /* Pull the success values from the original request packet. */ nb_flags = get_nb_flags(sent_nmb->additional->rdata); ttl = sent_nmb->additional->ttl; putip(®istered_ip,&sent_nmb->additional->rdata[2]); } } else { /* wins timeouts are special */ wins_registration_timeout(subrec, rrec); return; } DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n", success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name)); if(success) { /* Enter the registered name into the subnet name database before calling the success function. */ standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip); } else { struct nmb_name qname = *question_name; if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ standard_fail_register( subrec, &qname); } /* Ensure we don't retry. */ remove_response_record(subrec, rrec); }
/******************************************************** resolve via "hosts" method *********************************************************/ static BOOL resolve_hosts(const char *name, struct in_addr *return_ip) { /* * "host" means do a localhost, or dns lookup. */ struct hostent *hp; DEBUG(3,("resolve_name: Attempting host lookup for name %s<0x20>\n", name)); if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) { putip((char *)return_ip,(char *)hp->h_addr); return True; } return False; }
static void wins_next_registration(struct response_record *rrec) { struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; struct nmb_name *nmbname = &sent_nmb->question.question_name; uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata); struct userdata_struct *userdata = rrec->userdata; const char *tag; struct in_addr last_ip; struct subnet_record *subrec; putip(&last_ip,&sent_nmb->additional->rdata[2]); if (!userdata) { /* it wasn't multi-homed */ return; } tag = (const char *)userdata->data; for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { if (ip_equal(last_ip, subrec->myip)) { subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec); break; } } if (!subrec) { /* no more to do! */ return; } switch (sent_nmb->header.opcode) { case NMB_NAME_MULTIHOMED_REG_OPCODE: multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag); break; case NMB_NAME_REFRESH_OPCODE_8: queue_wins_refresh(nmbname, register_name_response, register_name_timeout_response, nb_flags, subrec->myip, tag); break; } }
void estadisticas(int *tiempopac,unsigned char *tuip,int pac) { int min,max,med=0; min=tiempopac[0]; max=tiempopac[0]; for(i=0;i<ctapac[1];i++) { //printf("%d ",tiempopac[i]); if(tiempopac[i]<min) min=tiempopac[i]; if(tiempopac[i]>max) max=tiempopac[i]; med=med+tiempopac[i]; } med=med/ctapac[1]; printf("\n\nestadisticas ping para ");putip(tuip);puts(":\n"); printf("paquetes enviados=%d, recividos=%d, perdidos=%d\n",ctapac[0],ctapac[1],ctapac[2]); printf("(%d %% ",(ctapac[2]*100)/pac);printf("perdidos),\n"); printf("tiempos aproximados de ida y vuelta en milisegundos:\n"); printf("minimo=%dms, maximo=%dms, media=%dms\n\n",min,max,med); }
/**************************************************************************** send a single packet to a port on another machine ****************************************************************************/ BOOL send_one_packet (char *buf, int len, struct in_addr ip, int port, int type) { BOOL ret; int out_fd; struct sockaddr_in sock_out; if (passive) return (True); /* create a socket to write to */ out_fd = socket (AF_INET, type, 0); if (out_fd == -1) { DEBUG (0, ("socket failed")); return False; } /* 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; if (DEBUGLEVEL > 0) DEBUG (3, ("sending a packet of len %d to (%s) on port %d of type %s\n", len, inet_ntoa (ip), port, type == SOCK_DGRAM ? "DGRAM" : "STREAM")); /* send it */ ret = (sendto (out_fd, buf, len, 0, (struct sockaddr *) &sock_out, sizeof (sock_out)) >= 0); if (!ret) DEBUG (0, ("Packet send to %s(%d) failed ERRNO=%s\n", inet_ntoa (ip), port, unix_error_string (errno))); close (out_fd); return (ret); }
BOOL cli_session_request(struct cli_state *cli, struct nmb_name *calling, struct nmb_name *called) { char *p; int len = 4; extern pstring user_socket_options; /* 445 doesn't have session request */ if (cli->port == 445) return True; /* send a session request (RFC 1002) */ memcpy(&(cli->calling), calling, sizeof(*calling)); memcpy(&(cli->called ), called , sizeof(*called )); /* put in the destination name */ p = cli->outbuf+len; name_mangle(cli->called .name, p, cli->called .name_type); len += name_len(p); /* and my name */ p = cli->outbuf+len; name_mangle(cli->calling.name, p, cli->calling.name_type); len += name_len(p); /* setup the packet length * Remove four bytes from the length count, since the length * field in the NBT Session Service header counts the number * of bytes which follow. The cli_send_smb() function knows * about this and accounts for those four bytes. * CRH. */ len -= 4; _smb_setlen(cli->outbuf,len); SCVAL(cli->outbuf,0,0x81); #ifdef WITH_SSL retry: #endif /* WITH_SSL */ cli_send_smb(cli); DEBUG(5,("Sent session request\n")); if (!cli_receive_smb(cli)) return False; if (CVAL(cli->inbuf,0) == 0x84) { /* C. Hoch 9/14/95 Start */ /* For information, here is the response structure. * We do the byte-twiddling to for portability. struct RetargetResponse{ unsigned char type; unsigned char flags; int16 length; int32 ip_addr; int16 port; }; */ int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9); /* SESSION RETARGET */ putip((char *)&cli->dest_ip,cli->inbuf+4); cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); if (cli->fd == -1) return False; DEBUG(3,("Retargeted\n")); set_socket_options(cli->fd,user_socket_options); /* Try again */ { static int depth; BOOL ret; if (depth > 4) { DEBUG(0,("Retarget recursion - failing\n")); return False; } depth++; ret = cli_session_request(cli, calling, called); depth--; return ret; } } /* C. Hoch 9/14/95 End */ #ifdef WITH_SSL if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */ if (!sslutil_fd_is_ssl(cli->fd)){ if (sslutil_connect(cli->fd) == 0) goto retry; } } #endif /* WITH_SSL */ if (CVAL(cli->inbuf,0) != 0x82) { /* This is the wrong place to put the error... JRA. */ cli->rap_error = CVAL(cli->inbuf,4); return False; } return(True); }
static void register_name_response(struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { /* * If we are registering broadcast, then getting a response is an * error - we do not have the name. If we are registering unicast, * then we expect to get a response. */ struct nmb_packet *nmb = &p->packet.nmb; BOOL bcast = nmb->header.nm_flags.bcast; BOOL success = True; struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; struct nmb_name *answer_name = &nmb->answers->rr_name; struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; int ttl = 0; uint16 nb_flags = 0; struct in_addr register_ip; fstring reg_name; putip(®ister_ip,&sent_nmb->additional->rdata[2]); fstrcpy(reg_name, inet_ntoa(register_ip)); if (subrec == unicast_subnet) { /* we know that this wins server is definately alive - for the moment! */ wins_srv_alive(rrec->packet->ip, register_ip); } /* Sanity check. Ensure that the answer name in the incoming packet is the same as the requested name in the outgoing packet. */ if(!question_name || !answer_name) { DEBUG(0,("register_name_response: malformed response (%s is NULL).\n", question_name ? "question_name" : "answer_name" )); return; } if(!nmb_name_equal(question_name, answer_name)) { DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); return; } if(bcast) { /* * Special hack to cope with old Samba nmbd's. * Earlier versions of Samba (up to 1.9.16p11) respond * to a broadcast name registration of WORKGROUP<1b> when * they should not. Hence, until these versions are gone, * we should treat such errors as success for this particular * case only. [email protected]. */ #if 1 /* OLD_SAMBA_SERVER_HACK */ unstring ans_name; pull_ascii_nstring(ans_name, sizeof(ans_name), answer_name->name); if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) && (answer_name->name_type == 0x1b)) { /* Pretend we did not get this. */ rrec->num_msgs--; DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n", nmb_namestr(answer_name))); return; } #endif /* OLD_SAMBA_SERVER_HACK */ /* Someone else has the name. Log the problem. */ DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n", nmb_namestr(answer_name), reg_name, subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip))); success = False; } else { /* Unicast - check to see if the response allows us to have the name. */ if (nmb->header.opcode == NMB_WACK_OPCODE) { /* WINS server is telling us to wait. Pretend we didn't get the response but don't send out any more register requests. */ DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n", inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name)); rrec->repeat_count = 0; /* How long we should wait for. */ rrec->repeat_time = p->timestamp + nmb->answers->ttl; rrec->num_msgs--; return; } else if (nmb->header.rcode != 0) { /* Error code - we didn't get the name. */ success = False; DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n", subrec==unicast_subnet?"WINS ":"", inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name, nmb->header.rcode)); } else { success = True; /* Get the data we need to pass to the success function. */ nb_flags = get_nb_flags(nmb->answers->rdata); ttl = nmb->answers->ttl; /* send off a registration for the next IP, if any */ wins_next_registration(rrec); } } DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n", success ? "success" : "failure", subrec==unicast_subnet?"WINS ":"", nmb_namestr(answer_name), reg_name, inet_ntoa(rrec->packet->ip))); if(success) { /* Enter the registered name into the subnet name database before calling the success function. */ standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); if( rrec->success_fn) (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip); } else { if( rrec->fail_fn) (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name); /* Remove the name. */ standard_fail_register( subrec, rrec, question_name); } /* Ensure we don't retry. */ remove_response_record(subrec, rrec); }
static void wins_registration_timeout(struct subnet_record *subrec, struct response_record *rrec) { struct userdata_struct *userdata = rrec->userdata; struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; struct nmb_name *nmbname = &sent_nmb->question.question_name; struct in_addr register_ip; fstring src_addr; putip(®ister_ip,&sent_nmb->additional->rdata[2]); fstrcpy(src_addr, inet_ntoa(register_ip)); DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n", inet_ntoa(rrec->packet->ip), src_addr)); /* mark it temporarily dead for this source address */ wins_srv_died(rrec->packet->ip, register_ip); /* if we have some userdata then use that to work out what wins server to try next */ if (userdata) { const char *tag = (const char *)userdata->data; /* try the next wins server in our failover list for this tag */ rrec->packet->ip = wins_srv_ip_tag(tag, register_ip); } /* if we have run out of wins servers for this tag then they must all have timed out. We treat this as *success*, not failure, and go into our standard name refresh mode. This copes with all the wins servers being down */ if (wins_srv_is_dead(rrec->packet->ip, register_ip)) { uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata); int ttl = sent_nmb->additional->ttl; standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip); if(rrec->success_fn) { (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, nmbname, nb_flags, ttl, register_ip); } /* send off a registration for the next IP, if any */ wins_next_registration(rrec); /* don't need to send this packet any more */ remove_response_record(subrec, rrec); return; } /* we will be moving to the next WINS server for this group, send it immediately */ rrec->repeat_count = 2; rrec->repeat_time = time(NULL) + 1; rrec->in_expiration_processing = False; DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n", nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip))); /* notice that we don't remove the response record. This keeps us trying to register with each of our failover wins servers */ }
int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { struct sockaddr_in sock_out; int res,ret; int connect_loop = 250; /* 250 milliseconds */ int loops = (timeout) / connect_loop; /* create a socket to write to */ res = socket(PF_INET, type, 0); if (res == -1) { DEBUG(0,("socket error\n")); return -1; } if (type != SOCK_STREAM) return(res); memset((char *)&sock_out,'\0',sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); sock_out.sin_port = htons( port ); sock_out.sin_family = PF_INET; /* set it non-blocking */ set_blocking(res,False); DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); /* and connect it to the destination */ connect_again: ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); /* Some systems return EAGAIN when they mean EINPROGRESS */ if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN) && loops--) { msleep(connect_loop); goto connect_again; } if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || errno == EAGAIN)) { DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); close(res); return -1; } #ifdef EISCONN if (ret < 0 && errno == EISCONN) { errno = 0; ret = 0; } #endif if (ret < 0) { DEBUG(1,("error connecting to %s:%d (%s)\n", inet_ntoa(*addr),port,strerror(errno))); close(res); return -1; } /* set it blocking again */ set_blocking(res,True); return res; }
static void release_name_response(struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { /* * If we are releasing broadcast, then getting a response is an * error. If we are releasing unicast, then we expect to get a response. */ struct nmb_packet *nmb = &p->packet.nmb; bool bcast = nmb->header.nm_flags.bcast; bool success = True; struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; struct nmb_name *answer_name = &nmb->answers->rr_name; struct in_addr released_ip; /* Sanity check. Ensure that the answer name in the incoming packet is the same as the requested name in the outgoing packet. */ if (!nmb_name_equal(question_name, answer_name)) { DEBUG(0,("release_name_response: Answer name %s differs from question name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); return; } if (bcast) { /* Someone sent a response to a bcast release? ignore it. */ return; } /* Unicast - check to see if the response allows us to release the name. */ if (nmb->header.rcode != 0) { /* Error code - we were told not to release the name ! What now ! */ success = False; DEBUG(0,("release_name_response: WINS server at IP %s rejected our \ name release of name %s with error code %d.\n", inet_ntoa(p->ip), nmb_namestr(answer_name), nmb->header.rcode)); } else if (nmb->header.opcode == NMB_WACK_OPCODE) { /* WINS server is telling us to wait. Pretend we didn't get the response but don't send out any more release requests. */ DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \ name %s on subnet %s.\n", inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->subnet_name)); rrec->repeat_count = 0; /* How long we should wait for. */ rrec->repeat_time = p->timestamp + nmb->answers->ttl; rrec->num_msgs--; return; } DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n", success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name)); if (success) { putip((char*)&released_ip ,&nmb->answers->rdata[2]); if(rrec->success_fn) (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip); standard_success_release( subrec, rrec->userdata, answer_name, released_ip); } else { /* We have no standard_fail_release - maybe we should add one ? */ if (rrec->fail_fn) { (*(release_name_fail_function)rrec->fail_fn)(subrec, rrec, answer_name); } } remove_response_record(subrec, rrec); }
/**************************************************************************** do a netbios name query to find someones IP returns an array of IP addresses or NULL if none *count will be set to the number of addresses returned ****************************************************************************/ struct in_addr * name_query (int fd, const char *name, int name_type, BOOL bcast, BOOL recurse, struct in_addr to_ip, int *count, void (*fn) (struct packet_struct *)) { BOOL found = False; int i, retries = 3; int retry_time = bcast ? 250 : 2000; struct timeval tval; struct packet_struct p; struct packet_struct *p2; struct nmb_packet *nmb = &p.packet.nmb; static int name_trn_id = 0; struct in_addr *ip_list = NULL; memset ((char *) &p, '\0', sizeof (p)); (*count) = 0; if (!name_trn_id) name_trn_id = ((unsigned) time (NULL) % (unsigned) 0x7FFF) + ((unsigned) getpid () % (unsigned) 100); name_trn_id = (name_trn_id + 1) % (unsigned) 0x7FFF; nmb->header.name_trn_id = name_trn_id; nmb->header.opcode = 0; nmb->header.response = False; nmb->header.nm_flags.bcast = bcast; nmb->header.nm_flags.recursion_available = False; nmb->header.nm_flags.recursion_desired = recurse; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = False; nmb->header.rcode = 0; nmb->header.qdcount = 1; nmb->header.ancount = 0; nmb->header.nscount = 0; nmb->header.arcount = 0; make_nmb_name (&nmb->question.question_name, name, name_type); nmb->question.question_type = 0x20; nmb->question.question_class = 0x1; p.ip = to_ip; p.port = NMB_PORT; p.fd = fd; p.timestamp = time (NULL); p.packet_type = NMB_PACKET; GetTimeOfDay (&tval); if (!send_packet (&p)) return NULL; retries--; while (1) { struct timeval tval2; GetTimeOfDay (&tval2); if (TvalDiff (&tval, &tval2) > retry_time) { if (!retries) break; if (!found && !send_packet (&p)) return NULL; GetTimeOfDay (&tval); retries--; } if ((p2 = receive_packet (fd, NMB_PACKET, 90))) { struct nmb_packet *nmb2 = &p2->packet.nmb; debug_nmb_packet (p2); if (nmb->header.name_trn_id != nmb2->header.name_trn_id || !nmb2->header.response) { /* * Its not for us - maybe deal with it later * (put it on the queue?). */ if (fn) fn (p2); else free_packet (p2); continue; } if (nmb2->header.opcode != 0 || nmb2->header.nm_flags.bcast || nmb2->header.rcode || !nmb2->header.ancount) { /* * XXXX what do we do with this? Could be a redirect, but * we'll discard it for the moment. */ free_packet (p2); continue; } ip_list = (struct in_addr *) Realloc (ip_list, sizeof (ip_list[0]) * ((*count) + nmb2->answers->rdlength / 6)); if (ip_list) { DEBUG (fn ? 3 : 2, ("Got a positive name query response from %s ( ", inet_ntoa (p2->ip))); for (i = 0; i < nmb2->answers->rdlength / 6; i++) { putip ((char *) &ip_list[(*count)], &nmb2->answers->rdata[2 + i * 6]); DEBUG (fn ? 3 : 2, ("%s ", inet_ntoa (ip_list[(*count)]))); (*count)++; } DEBUG (fn ? 3 : 2, (")\n")); } found = True; retries = 0; free_packet (p2); if (fn) break; /* * If we're doing a unicast lookup we only * expect one reply. Don't wait the full 2 * seconds if we got one. JRA. */ if (!bcast && found) break; } } return ip_list; }
/**************************************************************************** send a session request. see rfc1002.txt 4.3 and 4.3.2 ****************************************************************************/ BOOL cli_session_request(struct cli_state *cli, const struct nmb_name *calling, const struct nmb_name *called) { char *p; int len = 4; extern pstring user_socket_options; io_struct ps; uchar nb_type; ZERO_STRUCT(ps); io_init(&ps, 4096, MARSHALL); /* send a session request (RFC 1002) */ smb_set_nbnames(cli->hnd, calling, called); /* put in the destination name */ p = ps.data_p; name_mangle(called->name, p, called->name_type); len += name_len(p); /* and my name */ p = ps.data_p + len-4; name_mangle(calling->name, p, calling->name_type); len += name_len(p); ps.data_offset = len; smb_send_smb(cli->hnd, &ps, 0x81); io_free(&ps); DEBUG(5, ("Sent session request: %s to %s\n", nmb_namestr(calling), nmb_namestr(called))); if (!smb_receive_smb(cli->hnd, &ps, &nb_type)) return False; if (nb_type == 0x84) { int fd; /* C. Hoch 9/14/95 Start */ /* For information, here is the response structure. * We do the byte-twiddling to for portability. struct RetargetResponse{ unsigned char type; unsigned char flags; int16 length; int32 ip_addr; int16 port; }; */ int port = (CVAL(ps.data_p, 4) << 8) + CVAL(ps.data_p, 5); /* SESSION RETARGET */ putip((char *)&cli->dest_ip, ps.data_p); fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT); if (fd == -1 || !smb_set_fd(cli->hnd, fd)) return False; cli->dbg(3, "Retargeted\n"); set_socket_options(fd, user_socket_options); /* Try again */ { static int depth; BOOL ret; if (depth > 4) { cli->dbg( 0, "Retarget recursion - failing\n"); return False; } depth++; ret = cli_session_request(cli, calling, called); depth--; return ret; } } /* C. Hoch 9/14/95 End */ if (nb_type != 0x82) { /* This is the wrong place to put the error... JRA. */ cli->rap_error = CVAL(ps.data_p, 0); return False; } return (True); }
static void domain_master_node_status_success(struct subnet_record *subrec, struct userdata_struct *userdata, struct res_rec *answers, struct in_addr from_ip) { struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data); if( work == NULL ) { if( DEBUGLVL( 0 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Unable to find workgroup " ); dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name ); } return; } if( DEBUGLVL( 3 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Success in node status for workgroup " ); dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) ); } /* Go through the list of names found at answers->rdata and look for the first SERVER<0x20> name. */ if(answers->rdata != NULL) { char *p = answers->rdata; int numnames = CVAL(p, 0); p += 1; while (numnames--) { char qname[17]; uint16 nb_flags; int name_type; StrnCpy(qname,p,15); name_type = CVAL(p,15); nb_flags = get_nb_flags(&p[16]); trim_string(qname,NULL," "); p += 18; if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) { struct nmb_name nmbname; make_nmb_name(&nmbname, qname, name_type); /* Copy the dmb name and IP address into the workgroup struct. */ work->dmb_name = nmbname; putip((char *)&work->dmb_addr, &from_ip); /* Do the local master browser announcement to the domain master browser name and IP. */ announce_local_master_browser_to_domain_master_browser( work ); /* Now synchronise lists with the domain master browser. */ sync_with_dmb(work); break; } } } else if( DEBUGLVL( 0 ) ) { dbgtext( "domain_master_node_status_success:\n" ); dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " ); dbgtext( "%s.\n", inet_ntoa(from_ip) ); } }
static void find_domain_master_name_query_success(struct subnet_record *subrec, struct userdata_struct *userdata_in, struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) { /* * Unfortunately, finding the IP address of the Domain Master Browser, * as we have here, is not enough. We need to now do a sync to the * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will * respond to the SMBSERVER name. To get this name from IP * address we do a Node status request, and look for the first * NAME<0x20> in the response, and take that as the server name. * We also keep a cache of the Domain Master Browser name for this * workgroup in the Workgroup struct, so that if the same IP addess * is returned every time, we don't need to do the node status * request. */ struct work_record *work; struct nmb_name nmbname; struct userdata_struct *userdata; int size = sizeof(struct userdata_struct) + sizeof(fstring)+1; if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) ) { if( DEBUGLVL( 0 ) ) { dbgtext( "find_domain_master_name_query_success:\n" ); dbgtext( "Failed to find workgroup %s\n", q_name->name ); } return; } /* First check if we already have a dmb for this workgroup. */ if(!ip_equal(work->dmb_addr, ipzero) && ip_equal(work->dmb_addr, answer_ip)) { /* Do the local master browser announcement to the domain master browser name and IP. */ announce_local_master_browser_to_domain_master_browser( work ); /* Now synchronise lists with the domain master browser. */ sync_with_dmb(work); return; } else putip((char *)&work->dmb_addr, &ipzero); /* Now initiate the node status request. */ make_nmb_name(&nmbname,"*",0x0); /* Put the workgroup name into the userdata so we know what workgroup we're talking to when the reply comes back. */ /* Setup the userdata_struct - this is copied so we can use a stack variable for this. */ if((userdata = (struct userdata_struct *)malloc(size)) == NULL) { DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n")); return; } userdata->copy_fn = NULL; userdata->free_fn = NULL; userdata->userdata_len = strlen(work->work_group)+1; pstrcpy(userdata->data, work->work_group); node_status( subrec, &nmbname, answer_ip, domain_master_node_status_success, domain_master_node_status_fail, userdata); zero_free(userdata, size); }
static struct work_record *create_workgroup(char *name, int ttl) { struct work_record *work; struct subnet_record *subrec; int t = -1; if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) { DEBUG(0,("create_workgroup: malloc fail !\n")); return NULL; } bzero((char *)work, sizeof(*work)); StrnCpy(work->work_group,name,sizeof(work->work_group)-1); work->serverlist = NULL; work->RunningElection = False; work->ElectionCount = 0; work->announce_interval = 0; work->needelection = False; work->needannounce = True; work->lastannounce_time = time(NULL); work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; work->dom_state = DOMAIN_NONE; work->log_state = LOGON_NONE; work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; /* Make sure all token representations of workgroups are unique. */ for (subrec = FIRST_SUBNET; subrec && (t == -1); subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { struct work_record *w; for (w = subrec->workgrouplist; w && t == -1; w = w->next) { if (strequal(w->work_group, work->work_group)) t = w->token; } } if (t == -1) work->token = ++workgroup_count; else work->token = t; /* No known local master browser as yet. */ *work->local_master_browser_name = '\0'; /* No known domain master browser as yet. */ *work->dmb_name.name = '\0'; putip((char *)&work->dmb_addr, &ipzero); /* WfWg uses 01040b01 */ /* Win95 uses 01041501 */ /* NTAS uses ???????? */ work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); work->ElectionCriterion |= (lp_os_level() << 24); if (lp_domain_master()) work->ElectionCriterion |= 0x80; return work; }