ei_connect.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 1,724 行 · 第 1/3 页
C
1,724 行
#endifstatic void gen_digest(unsigned challenge, char cookie[], unsigned char digest[16]){ MD5_CTX c; char chbuf[20]; sprintf(chbuf,"%u", challenge); ei_MD5Init(&c); ei_MD5Update(&c, (unsigned char *) cookie, (unsigned) strlen(cookie)); ei_MD5Update(&c, (unsigned char *) chbuf, (unsigned) strlen(chbuf)); ei_MD5Final(digest, &c);}static char *hex(char digest[16]){ unsigned char *d = (unsigned char *) digest; /* FIXME problem for threaded ? */ static char buff[sizeof(digest)*2 + 1]; char *p = buff; static char tab[] = "0123456789abcdef"; int i; for (i = 0; i < sizeof(digest); ++i) { *p++ = tab[(int)((*d) >> 4)]; *p++ = tab[(int)((*d++) & 0xF)]; } *p = '\0'; return buff;}static int read_2byte_package(int fd, char **buf, int *buflen, int *is_static, unsigned ms){ unsigned char nbuf[2]; unsigned char *x = nbuf; unsigned len; int res; if((res = ei_read_fill_t(fd, nbuf, 2, ms)) != 2) { erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } len = get16be(x); if (len > *buflen) { if (*is_static) { char *tmp = malloc(len); if (!tmp) { erl_errno = ENOMEM; return -1; } *buf = tmp; *is_static = 0; *buflen = len; } else { char *tmp = realloc(*buf, len); if (!tmp) { erl_errno = ENOMEM; return -1; } *buf = tmp; *buflen = len; } } if ((res = ei_read_fill_t(fd, *buf, len, ms)) != len) { erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } return len;}static int send_status(int fd, char *status, unsigned ms){ char *buf, *s; char dbuf[DEFBUF_SIZ]; int siz = strlen(status) + 1 + 2; int res; buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf; if (!buf) { erl_errno = ENOMEM; return -1; } s = buf; put16be(s,siz - 2); put8(s, 's'); memcpy(s, status, strlen(status)); if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) { EI_TRACE_ERR0("send_status","-> SEND_STATUS socket write failed"); if (buf != dbuf) free(buf); erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } EI_TRACE_CONN1("send_status","-> SEND_STATUS (%s)",status); if (buf != dbuf) free(buf); return 0;}static int recv_status(int fd, unsigned ms){ char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) { EI_TRACE_ERR1("recv_status", "<- RECV_STATUS socket read failed (%d)", rlen); goto error; } if (rlen == 3 && buf[0] == 's' && buf[1] == 'o' && buf[2] == 'k') { if (!is_static) free(buf); EI_TRACE_CONN0("recv_status","<- RECV_STATUS (ok)"); return 0; }error: if (!is_static) free(buf); return -1;}/* FIXME fix the signed/unsigned mess..... */static int send_name_or_challenge(int fd, char *nodename, int f_chall, unsigned challenge, unsigned version, unsigned ms) { char *buf; unsigned char *s; char dbuf[DEFBUF_SIZ]; int siz = 2 + 1 + 2 + 4 + strlen(nodename); const char* function[] = {"SEND_NAME", "SEND_CHALLENGE"}; int res; if (f_chall) siz += 4; buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf; if (!buf) { erl_errno = ENOMEM; return -1; } s = (unsigned char *)buf; put16be(s,siz - 2); put8(s, 'n'); put16be(s, version); put32be(s, (DFLAG_EXTENDED_REFERENCES | DFLAG_EXTENDED_PIDS_PORTS | DFLAG_FUN_TAGS | DFLAG_NEW_FUN_TAGS)); if (f_chall) put32be(s, challenge); memcpy(s, nodename, strlen(nodename)); if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) { EI_TRACE_ERR1("send_name_or_challenge", "-> %s socket write failed", function[f_chall]); if (buf != dbuf) free(buf); erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } if (buf != dbuf) free(buf); return 0;}static int recv_challenge(int fd, unsigned *challenge, unsigned *version, unsigned *flags, ErlConnect *namebuf, unsigned ms){ char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; char *s; struct sockaddr_in sin; int sin_len = sizeof(sin); char tag; erl_errno = EIO; /* Default */ if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) { EI_TRACE_ERR1("recv_challenge", "<- RECV_CHALLENGE socket read failed (%d)",rlen); goto error; } if ((rlen - 11) > MAXNODELEN) { EI_TRACE_ERR1("recv_challenge", "<- RECV_CHALLENGE nodename too long (%d)",rlen - 11); goto error; } s = buf; if ((tag = get8(s)) != 'n') { EI_TRACE_ERR2("recv_challenge", "<- RECV_CHALLENGE incorrect tag, " "expected 'n' got '%c' (%u)",tag,tag); goto error; } *version = get16be(s); *flags = get32be(s); *challenge = get32be(s); if (!(*flags & DFLAG_EXTENDED_REFERENCES)) { EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot " "handle extended references"); goto error; } if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS) && !ei_internal_use_r9_pids_ports()) { EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot " "handle extended pids and ports"); erl_errno = EIO; goto error; } if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) { EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE can't get peername"); erl_errno = errno; goto error; } memcpy(namebuf->ipadr, &(sin.sin_addr.s_addr), sizeof(sin.sin_addr.s_addr)); memcpy(namebuf->nodename, s, rlen - 11); namebuf->nodename[rlen - 11] = '\0'; if (!is_static) free(buf); EI_TRACE_CONN4("recv_challenge","<- RECV_CHALLENGE (ok) node = %s, " "version = %u, " "flags = %u, " "challenge = %d", namebuf->nodename, *version, *flags, *challenge ); erl_errno = 0; return 0;error: if (!is_static) free(buf); return -1;}static int send_challenge_reply(int fd, unsigned char digest[16], unsigned challenge, unsigned ms) { char *s; char buf[DEFBUF_SIZ]; int siz = 2 + 1 + 4 + 16; int res; s = buf; put16be(s,siz - 2); put8(s, 'r'); put32be(s, challenge); memcpy(s, digest, 16); if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) { EI_TRACE_ERR0("send_challenge_reply", "-> SEND_CHALLENGE_REPLY socket write failed"); erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } EI_TRACE_CONN2("send_challenge_reply", "-> SEND_CHALLENGE_REPLY (ok) challenge = %d, digest = %s", challenge,hex(digest)); return 0;}static int recv_challenge_reply (int fd, unsigned our_challenge, char cookie[], unsigned *her_challenge, unsigned ms){ char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; char *s; char tag; char her_digest[16], expected_digest[16]; erl_errno = EIO; /* Default */ if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 21) { EI_TRACE_ERR1("recv_challenge_reply", "<- RECV_CHALLENGE_REPLY socket read failed (%d)",rlen); goto error; } s = buf; if ((tag = get8(s)) != 'r') { EI_TRACE_ERR2("recv_challenge_reply", "<- RECV_CHALLENGE_REPLY incorrect tag, " "expected 'r' got '%c' (%u)",tag,tag); goto error; } *her_challenge = get32be(s); memcpy(her_digest, s, 16); gen_digest(our_challenge, cookie, (unsigned char*)expected_digest); if (memcmp(her_digest, expected_digest, 16)) { EI_TRACE_ERR0("recv_challenge_reply", "<- RECV_CHALLENGE_REPLY authorization failure"); goto error; } if (!is_static) free(buf); EI_TRACE_CONN2("recv_challenge_reply", "<- RECV_CHALLENGE_REPLY (ok) challenge = %u, digest = %s", *her_challenge,hex(her_digest)); erl_errno = 0; return 0; error: if (!is_static) free(buf); return -1;}static int send_challenge_ack(int fd, unsigned char digest[16], unsigned ms) { char *s; char buf[DEFBUF_SIZ]; int siz = 2 + 1 + 16; int res; s = buf; put16be(s,siz - 2); put8(s, 'a'); memcpy(s, digest, 16); if ((res = ei_write_fill_t(fd, buf, siz, ms)) != siz) { EI_TRACE_ERR0("recv_challenge_reply", "-> SEND_CHALLENGE_ACK socket write failed"); erl_errno = (res == -2) ? ETIMEDOUT : EIO; return -1; } EI_TRACE_CONN1("recv_challenge_reply", "-> SEND_CHALLENGE_ACK (ok) digest = %s",hex(digest)); return 0;}static int recv_challenge_ack(int fd, unsigned our_challenge, char cookie[], unsigned ms){ char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; char *s; char tag; char her_digest[16], expected_digest[16]; erl_errno = EIO; /* Default */ if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) != 17) { EI_TRACE_ERR1("recv_challenge_ack", "<- RECV_CHALLENGE_ACK socket read failed (%d)",rlen); goto error; } s = buf; if ((tag = get8(s)) != 'a') { EI_TRACE_ERR2("recv_challenge_ack", "<- RECV_CHALLENGE_ACK incorrect tag, " "expected 'a' got '%c' (%u)",tag,tag); goto error; } memcpy(her_digest, s, 16); gen_digest(our_challenge, cookie, (unsigned char *)expected_digest); if (memcmp(her_digest, expected_digest, 16)) { EI_TRACE_ERR0("recv_challenge_ack", "<- RECV_CHALLENGE_ACK authorization failure"); goto error; } if (!is_static) free(buf); EI_TRACE_CONN1("recv_challenge_ack", "<- RECV_CHALLENGE_ACK (ok) digest = %s",hex(her_digest)); erl_errno = 0; return 0;error: if (!is_static) free(buf); return -1;}static int send_name(int fd, char *nodename, unsigned version, unsigned ms) { return send_name_or_challenge(fd, nodename, 0, 0, version, ms);}static int send_challenge(int fd, char *nodename, unsigned challenge, unsigned version, unsigned ms){ return send_name_or_challenge(fd, nodename, 1, challenge, version, ms);}static int recv_name(int fd, unsigned *version, unsigned *flags, ErlConnect *namebuf, unsigned ms){ char dbuf[DEFBUF_SIZ]; char *buf = dbuf; int is_static = 1; int buflen = DEFBUF_SIZ; int rlen; char *s; struct sockaddr_in sin; int sin_len = sizeof(sin); char tag; erl_errno = EIO; /* Default */ if ((rlen = read_2byte_package(fd, &buf, &buflen, &is_static, ms)) <= 0) { EI_TRACE_ERR1("recv_name","<- RECV_NAME socket read failed (%d)",rlen); goto error; } if ((rlen - 7) > MAXNODELEN) { EI_TRACE_ERR1("recv_name","<- RECV_NAME nodename too long (%d)",rlen-7); goto error; } s = buf; tag = get8(s); if (tag != 'n') { EI_TRACE_ERR2("recv_name","<- RECV_NAME incorrect tag, " "expected 'n' got '%c' (%u)",tag,tag); goto error; } *version = get16be(s); *flags = get32be(s); if (!(*flags & DFLAG_EXTENDED_REFERENCES)) { EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot handle" "extended references"); goto error; } if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS) && !ei_internal_use_r9_pids_ports()) { EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot " "handle extended pids and ports"); erl_errno = EIO; goto error; } if (getpeername(fd, (struct sockaddr *) &sin, &sin_len) < 0) { EI_TRACE_ERR0("recv_name","<- RECV_NAME can't get peername"); erl_errno = errno; goto error; } memcpy(namebuf->ipadr, &(sin.sin_addr.s_addr), sizeof(sin.sin_addr.s_addr)); memcpy(namebuf->nodename, s, rlen - 7); namebuf->nodename[rlen - 7] = '\0'; if (!is_static) free(buf); EI_TRACE_CONN3("recv_name", "<- RECV_NAME (ok) node = %s, version = %u, flags = %u", namebuf->nodename,*version,*flags); erl_errno = 0; return 0; error: if (!is_static) free(buf); return -1;}/*************************************************************************** * * Returns 1 on success and 0 on failure. * ***************************************************************************//* size is the buffer size, e.i. string length + 1 */static int get_home(char *buf, int size){ char* homedrive; char* homepath; #ifdef __WIN32__ homedrive = getenv("HOMEDRIVE"); homepath = getenv("HOMEPATH");#else homedrive = ""; homepath = getenv("HOME");#endif if (!homedrive || !homepath) { buf[0] = '.'; buf[1] = '\0'; return 1; } else if (strlen(homedrive)+strlen(homepath) < size-1) { strcpy(buf, homedrive); strcat(buf, homepath); return 1; } return 0;}static int get_cookie(char *buf, int bufsize){ char fname[EI_MAX_HOME_PATH + sizeof(COOKIE_FILE) + 1]; int fd; int len; unsigned char next_c; if (!get_home(fname, EI_MAX_HOME_PATH+1)) { fprintf(stderr,"<ERROR> get_cookie: too long path to home"); return 0; } strcat(fname, COOKIE_FILE); if ((fd = open(fname, O_RDONLY, 0777)) < 0) { fprintf(stderr,"<ERROR> get_cookie: can't open cookie file"); return 0; } if ((len = read(fd, buf, bufsize-1)) < 0) { fprintf(stderr,"<ERROR> get_cookie: reading cookie file"); close(fd); return 0; } /* If more to read it is too long. Not 100% correct test but will do. */ if (read(fd, &next_c, 1) > 0 && !isspace(next_c)) { fprintf(stderr,"<ERROR> get_cookie: cookie in %s is too long",fname); close(fd); return 0; } close(fd); /* Remove all newlines after the first newline */ buf[len] = '\0'; /* Terminate string */ len = strcspn(buf,"\r\n"); buf[len] = '\0'; /* Terminate string again */ return 1; /* Success! */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?