/*parse the response message and manipulate the send message*/ static int handlemessage(struct dhcp_msg*rmsg,struct dhcp_msg*smsg) { int i,j,p; /*find DNS info*/ if(getdns){ p=messagefindoption(rmsg,OPT_DNS_SERVER); if(p>=0){ for(i=0;i<rmsg->msg_opt[p].opt_dns_server.num_dns;i++) addaddr(dnsservers,rmsg->msg_opt[p].opt_dns_server.addr[i]); } p=messagefindoption(rmsg,OPT_DNS_NAME); if(p>=0){ for(i=0;i<rmsg->msg_opt[p].opt_dns_name.num_dns;i++) adddomain(rmsg->msg_opt[p].opt_dns_name.namelist[i]); } } /*find PREFIX info*/ if(getprefix){ p=messagefindoption(rmsg,OPT_IAPD); if(p>=0) for(i=0;i<rmsg->msg_opt[p].opt_numopts;i++) if(rmsg->msg_opt[p].subopt[i].opt_type==OPT_IAPREFIX){ j=addaddr(prefixes,rmsg->msg_opt[p].subopt[i].opt_iaprefix.prefix); if(j>=0) prefixlens[j]=rmsg->msg_opt[p].subopt[i].opt_iaprefix.prefixlen; } } /*find IANA info*/ if(getaddress){ p=messagefindoption(rmsg,OPT_IANA); if(p>=0) for(i=0;i<rmsg->msg_opt[p].opt_numopts;i++) if(rmsg->msg_opt[p].subopt[i].opt_type==OPT_IAADDR) addaddr(addresses,rmsg->msg_opt[p].subopt[i].opt_iaaddress.addr); } /*copy server address*/ Memcpy(&dhcpserver,&rmsg->msg_peer.sin6_addr,16); /*check for rapid commit or type=REPLY; if so: tell caller it can stop now*/ if(rmsg->msg_type==MSG_REPLY)return 0; if(messagefindoption(rmsg,OPT_RAPIDCOMMIT)>=0)return 0; /*otherwise we need to continue*/ /*correct message type & id*/ clearrecvfilter(); if(getprefix||getaddress){ addrecvfilter(MSG_REPLY); smsg->msg_type=MSG_REQUEST; }else{ addrecvfilter(MSG_REPLY); smsg->msg_type=MSG_IREQUEST; } smsg->msg_id++; /*elapsed time continues to count*/ /*rapid commit is no longer applicable*/ messageremoveoption(smsg,OPT_RAPIDCOMMIT); /*append server ID*/ p=messagefindoption(rmsg,OPT_SERVERID); if(p>=0)messageappendopt(smsg,&rmsg->msg_opt[p]); return 1; }
void dynrelocsym(Sym *s) { Reloc *r; Sym *rel; Sym *got; if(HEADTYPE == Hwindows) { Sym *rel, *targ; rel = lookup(".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(rel, 0xff); adduint8(rel, 0x25); addaddr(rel, targ); adduint8(rel, 0x90); adduint8(rel, 0x90); } else { adduint8(rel, 0xff); adduint8(rel, 0x24); adduint8(rel, 0x25); addaddrplus4(rel, targ, 0); adduint8(rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } got = rel = nil; if(flag_shared) { rel = lookuprel(); got = lookup(".got", 0); } s->rel_ro = 0; for(r=s->r; r<s->r+s->nr; r++) { if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) adddynrel(s, r); if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR && (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) { // Create address based RELATIVE relocation adddynrela(rel, s, r); if(s->type < SNOPTRDATA) s->rel_ro = 1; } } }
void addstrdata(char *name, char *value) { LSym *s, *sp; char *p; uchar reachable; p = smprint("%s.str", name); sp = linklookup(ctxt, p, 0); free(p); addstring(sp, value); sp->type = SRODATA; s = linklookup(ctxt, name, 0); s->size = 0; s->dupok = 1; reachable = s->reachable; addaddr(ctxt, s, sp); adduint32(ctxt, s, strlen(value)); if(PtrSize == 8) adduint32(ctxt, s, 0); // round struct to pointer width // addstring, addaddr, etc., mark the symbols as reachable. // In this case that is not necessarily true, so stick to what // we know before entering this function. s->reachable = reachable; sp->reachable = reachable; }
void elfwritedynentsym(Sym *s, int tag, Sym *t) { if(elf64) adduint64(s, tag); else adduint32(s, tag); addaddr(s, t); }
void elfwritedynentsym(LSym *s, int tag, LSym *t) { if(elf64) adduint64(ctxt, s, tag); else adduint32(ctxt, s, tag); addaddr(ctxt, s, t); }
void adddynsym(Link *ctxt, LSym *s) { LSym *d; int t; char *name; if(s->dynid >= 0) return; if(iself) { s->dynid = nelfsym++; d = linklookup(ctxt, ".dynsym", 0); name = s->extname; adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(ctxt, d, t); /* reserved */ adduint8(ctxt, d, 0); /* section where symbol is defined */ if(s->type == SDYNIMPORT) adduint16(ctxt, d, SHN_UNDEF); else adduint16(ctxt, d, 1); /* value */ if(s->type == SDYNIMPORT) adduint64(ctxt, d, 0); else addaddr(ctxt, d, s); /* size of object */ adduint64(ctxt, d, s->size); if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(linklookup(ctxt, ".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); } else if(HEADTYPE == Hwindows) { // already taken care of } else { diag("adddynsym: unsupported binary format"); } }
void dynrelocsym(LSym *s) { Reloc *r; if(HEADTYPE == Hwindows) { LSym *rel, *targ; rel = linklookup(ctxt, ".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(targ == nil) continue; if(!targ->reachable) diag("internal inconsistency: dynamic symbol %s is not reachable.", targ->name); if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(ctxt, rel, 0xff); adduint8(ctxt, rel, 0x25); addaddr(ctxt, rel, targ); adduint8(ctxt, rel, 0x90); adduint8(ctxt, rel, 0x90); } else { adduint8(ctxt, rel, 0xff); adduint8(ctxt, rel, 0x24); adduint8(ctxt, rel, 0x25); addaddrplus4(ctxt, rel, targ, 0); adduint8(ctxt, rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } for(r=s->r; r<s->r+s->nr; r++) { if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) { if(r->sym != S && !r->sym->reachable) diag("internal inconsistency: dynamic symbol %s is not reachable.", r->sym->name); adddynrel(s, r); } } }
void addstrdata(char *name, char *value) { Sym *s, *sp; char *p; p = smprint("%s.str", name); sp = lookup(p, 0); free(p); addstring(sp, value); s = lookup(name, 0); s->dupok = 1; addaddr(s, sp); adduint32(s, strlen(value)); if(PtrSize == 8) adduint32(s, 0); // round struct to pointer width }
void dynrelocsym(Sym *s) { Reloc *r; if(HEADTYPE == Hwindows) { Sym *rel, *targ; rel = lookup(".rel", 0); if(s == rel) return; for(r=s->r; r<s->r+s->nr; r++) { targ = r->sym; if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files. targ->plt = rel->size; r->sym = rel; r->add = targ->plt; // jmp *addr if(thechar == '8') { adduint8(rel, 0xff); adduint8(rel, 0x25); addaddr(rel, targ); adduint8(rel, 0x90); adduint8(rel, 0x90); } else { adduint8(rel, 0xff); adduint8(rel, 0x24); adduint8(rel, 0x25); addaddrplus4(rel, targ, 0); adduint8(rel, 0x90); } } else if(r->sym->plt >= 0) { r->sym = rel; r->add = targ->plt; } } return; } for(r=s->r; r<s->r+s->nr; r++) if(r->sym->type == SDYNIMPORT || r->type >= 256) adddynrel(s, r); }
/* read address file */ void readaddrs(char *file) { Biobuf *b; char *p; b = Bopen(file, OREAD); if(b == nil) return; while((p = Brdline(b, '\n')) != nil){ p[Blinelen(b)-1] = 0; if(*p == '#') continue; if(*p == '!') remaddr(p+1); else addaddr(p); } Bterm(b); }
void addstrdata(char *name, char *value) { Sym *s, *sp; char *p; p = smprint("%s.str", name); sp = lookup(p, 0); free(p); addstring(sp, value); s = lookup(name, 0); s->size = 0; s->dupok = 1; addaddr(s, sp); adduint32(s, strlen(value)); if(PtrSize == 8) adduint32(s, 0); // round struct to pointer width // in case reachability has already been computed sp->reachable = s->reachable; }
void adddynsym(Sym *s) { Sym *d; int t; char *name; if(s->dynid >= 0) return; if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->extname; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(s->type == SDYNIMPORT) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); } else if(HEADTYPE == Hwindows) { // already taken care of } else { diag("adddynsym: unsupported binary format"); } }
void adddynsym(Sym *s) { Sym *d, *str; int t; char *name; vlong off; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { // Mach-O symbol nlist32 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps symgrow(d, ndynexp*12); } if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp() s->dynid = -s->dynid-100; off = s->dynid*12; } else { off = d->size; s->dynid = off/12; } // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); setuint32(d, off, str->size); off += 4; adduint8(str, '_'); addstring(str, name); if(s->type == SDYNIMPORT) { setuint8(d, off, 0x01); // type - N_EXT - external symbol off++; setuint8(d, off, 0); // section off++; } else { setuint8(d, off, 0x0f); off++; switch(s->type) { default: case STEXT: setuint8(d, off, 1); break; case SDATA: setuint8(d, off, 2); break; case SBSS: setuint8(d, off, 4); break; } off++; } setuint16(d, off, 0); // desc off += 2; if(s->type == SDYNIMPORT) setuint32(d, off, 0); // value else setaddr(d, off, s); off += 4; } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
void main(int argc, char **argv) { String *msg; String *firstline; char *listname, *alfile; Waitmsg *w; int fd; char *replytoname = nil; ARGBEGIN{ case 'r': replytoname = ARGF(); break; }ARGEND; rfork(RFENVG|RFREND); if(argc < 2) usage(); alfile = argv[0]; listname = argv[1]; if(replytoname == nil) replytoname = listname; readaddrs(alfile); if(Binit(&in, 0, OREAD) < 0) sysfatal("opening input: %r"); msg = s_new(); firstline = s_new(); /* discard the 'From ' line */ if(s_read_line(&in, firstline) == nil) sysfatal("reading input: %r"); /* read up to the first 128k of the message. more is ridiculous. Not if word documents are distributed. Upped it to 2MB (pb) */ if(s_read(&in, msg, 2*1024*1024) <= 0) sysfatal("reading input: %r"); /* parse the header */ yyinit(s_to_c(msg), s_len(msg)); yyparse(); /* get the sender */ getaddrs(); if(from == nil) from = sender; if(from == nil) sysfatal("message must contain From: or Sender:"); if(strcmp(listname, s_to_c(from)) == 0) sysfatal("can't remail messages from myself"); addaddr(s_to_c(from)); /* start the mailer up and return a pipe to it */ fd = startmailer(listname); /* send message adding our own reply-to and precedence */ printmsg(fd, msg, replytoname, listname); close(fd); /* wait for mailer to end */ while(w = wait()){ if(w->msg != nil && w->msg[0]) sysfatal("%s", w->msg); free(w); } /* if the mailbox exists, cat the mail to the end of it */ appendtoarchive(listname, firstline, msg); exits(0); }
void adddynsym(Sym *s) { Sym *d, *str; int t; char *name; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && s->type == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); /* reserved */ adduint8(d, 0); /* section where symbol is defined */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } /* value */ if(s->type == SDYNIMPORT) adduint64(d, 0); else addaddr(d, s); /* size of object */ adduint64(d, 0); if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) { elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(lookup(".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { // Mach-o symbol nlist64 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; s->dynid = d->size/16; // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); adduint32(d, str->size); adduint8(str, '_'); addstring(str, name); if(s->type == SDYNIMPORT) { adduint8(d, 0x01); // type - N_EXT - external symbol adduint8(d, 0); // section } else { adduint8(d, 0x0f); switch(s->type) { default: case STEXT: adduint8(d, 1); break; case SDATA: adduint8(d, 2); break; case SBSS: adduint8(d, 4); break; } } adduint16(d, 0); // desc if(s->type == SDYNIMPORT) adduint64(d, 0); // value else addaddr(d, s); } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
void adddynsym(Sym *s) { Sym *d, *str; int t; char *name; if(s->dynid >= 0) return; if(s->dynimpname == nil) diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0); if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ name = s->dynimpname; if(name == nil) name = s->name; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ if(s->type == SDYNIMPORT) adduint32(d, 0); else addaddr(d, s); /* size */ adduint32(d, 0); /* type */ t = STB_GLOBAL << 4; if(s->dynexport && s->type == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; adduint8(d, t); adduint8(d, 0); /* shndx */ if(!s->dynexport && s->dynimpname != nil) adduint16(d, SHN_UNDEF); else { switch(s->type) { default: case STEXT: t = 11; break; case SRODATA: t = 12; break; case SDATA: t = 13; break; case SBSS: t = 14; break; } adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { // Mach-O symbol nlist32 d = lookup(".dynsym", 0); name = s->dynimpname; if(name == nil) name = s->name; s->dynid = d->size/12; // darwin still puts _ prefixes on all C symbols str = lookup(".dynstr", 0); adduint32(d, str->size); adduint8(str, '_'); addstring(str, name); adduint8(d, 0x01); // type - N_EXT - external symbol adduint8(d, 0); // section adduint16(d, 0); // desc adduint32(d, 0); // value } else if(HEADTYPE != Hwindows) { diag("adddynsym: unsupported binary format"); } }
void patch(void) { int32 c; Prog *p, *q; Sym *s, *gmsym; int32 vexit; if(debug['v']) Bprint(&bso, "%5.2f mkfwd\n", cputime()); Bflush(&bso); mkfwd(); if(debug['v']) Bprint(&bso, "%5.2f patch\n", cputime()); Bflush(&bso); if(flag_shared) { s = lookup("init_array", 0); s->type = SINITARR; s->reachable = 1; s->hide = 1; addaddr(s, lookup(INITENTRY, 0)); } gmsym = lookup("runtime.tlsgm", 0); if(linkmode != LinkExternal) gmsym->reachable = 0; s = lookup("exit", 0); vexit = s->value; for(cursym = textp; cursym != nil; cursym = cursym->next) for(p = cursym->text; p != P; p = p->link) { if(HEADTYPE == Hwindows) { // Windows // Convert // op n(GS), reg // to // MOVL 0x28(GS), reg // op n(reg), reg // The purpose of this patch is to fix some accesses // to extern register variables (TLS) on Windows, as // a different method is used to access them. if(p->from.type == D_INDIR+D_GS && p->to.type >= D_AX && p->to.type <= D_DI && p->from.offset <= 8) { q = appendp(p); q->from = p->from; q->from.type = D_INDIR + p->to.type; q->to = p->to; q->as = p->as; p->as = AMOVQ; p->from.type = D_INDIR+D_GS; p->from.offset = 0x28; } } if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) { // ELF uses FS instead of GS. if(p->from.type == D_INDIR+D_GS) p->from.type = D_INDIR+D_FS; if(p->to.type == D_INDIR+D_GS) p->to.type = D_INDIR+D_FS; if(p->from.index == D_GS) p->from.index = D_FS; if(p->to.index == D_GS) p->to.index = D_FS; } if(!flag_shared) { // Convert g() or m() accesses of the form // op n(reg)(GS*1), reg // to // op n(GS*1), reg if(p->from.index == D_FS || p->from.index == D_GS) { p->from.type = D_INDIR + p->from.index; p->from.index = D_NONE; } // Convert g() or m() accesses of the form // op reg, n(reg)(GS*1) // to // op reg, n(GS*1) if(p->to.index == D_FS || p->to.index == D_GS) { p->to.type = D_INDIR + p->to.index; p->to.index = D_NONE; } // Convert get_tls access of the form // op runtime.tlsgm(SB), reg // to // NOP if(gmsym != S && p->from.sym == gmsym) { p->as = ANOP; p->from.type = D_NONE; p->to.type = D_NONE; p->from.sym = nil; p->to.sym = nil; continue; } } else { // Convert TLS reads of the form // op n(GS), reg // to // MOVQ $runtime.tlsgm(SB), reg // op n(reg)(GS*1), reg if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) { q = appendp(p); q->to = p->to; q->as = p->as; q->from.type = D_INDIR+p->to.type; q->from.index = p->from.type - D_INDIR; q->from.scale = 1; q->from.offset = p->from.offset; p->as = AMOVQ; p->from.type = D_EXTERN; p->from.sym = gmsym; p->from.offset = 0; } } if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) { s = p->to.sym; if(s) { if(debug['c']) Bprint(&bso, "%s calls %s\n", TNAME, s->name); if((s->type&SMASK) != STEXT) { /* diag prints TNAME first */ diag("undefined: %s", s->name); s->type = STEXT; s->value = vexit; continue; // avoid more error messages } if(s->text == nil) continue; p->to.type = D_BRANCH; p->to.offset = s->text->pc; p->pcond = s->text; continue; } } if(p->to.type != D_BRANCH) continue; c = p->to.offset; for(q = cursym->text; q != P;) { if(c == q->pc) break; if(q->forwd != P && c >= q->forwd->pc) q = q->forwd; else q = q->link; } if(q == P) { diag("branch out of range in %s (%#ux)\n%P [%s]", TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>"); p->to.type = D_NONE; } p->pcond = q; } for(cursym = textp; cursym != nil; cursym = cursym->next) for(p = cursym->text; p != P; p = p->link) { p->mark = 0; /* initialization for follow */ if(p->pcond != P) { p->pcond = brloop(p->pcond); if(p->pcond != P) if(p->to.type == D_BRANCH) p->to.offset = p->pcond->pc; } } }