plan 9 kernel history: overview | file list | diff list

2002/0307/port/devssl.c (diff list | history)

2002/0306/sys/src/9/port/devssl.c:111,1162002/0307/sys/src/9/port/devssl.c:111,117 (short | long | prev | next)
1996/1029    
static void	sslhangup(Dstate*); 
static Dstate*	dsclone(Chan *c); 
static void	dsnew(Chan *c, Dstate **); 
2002/0307    
static long	sslput(Dstate *s, Block * volatile b); 
1995/1217    
 
2000/0325    
char *sslnames[] = { 
[Qclonus]	"clone", 
2002/0306/sys/src/9/port/devssl.c:542,5812002/0307/sys/src/9/port/devssl.c:543,582
1997/0327    
static Block* 
1998/0327    
sslbread(Chan *c, long n, ulong) 
1995/1213    
{ 
1996/0531    
	volatile struct { Dstate *s; } s; 
2002/0307    
	Dstate * volatile s; 
1995/1218    
	Block *b; 
2001/0825    
	uchar consumed[3], *p; 
	int toconsume; 
1996/1029    
	int len, pad; 
1995/1217    
 
1996/1029    
	s.s = dstate[CONV(c->qid)]; 
	if(s.s == 0) 
2002/0307    
	s = dstate[CONV(c->qid)]; 
	if(s == 0) 
1996/1029    
		panic("sslbread"); 
	if(s.s->state == Sincomplete) 
2002/0307    
	if(s->state == Sincomplete) 
1995/1217    
		error(Ebadusefd); 
 
2001/0825    
	qlock(&s.s->in.q); 
2002/0307    
	qlock(&s->in.q); 
1995/1217    
	if(waserror()){ 
1996/0531    
		qunlock(&s.s->in.q); 
2002/0307    
		qunlock(&s->in.q); 
1995/1217    
		nexterror(); 
1995/1213    
	} 
1995/1217    
 
1996/1029    
	if(s.s->processed == 0){ 
2002/0307    
	if(s->processed == 0){ 
2001/0825    
		/* 
		 * Read in the whole message.  Until we've got it all, 
		 * it stays on s.s->unprocessed, so that if we get Eintr, 
2002/0307    
		 * it stays on s->unprocessed, so that if we get Eintr, 
2001/0825    
		 * we'll pick up where we left off. 
		 */ 
		ensure(s.s, &s.s->unprocessed, 3); 
		s.s->unprocessed = pullupblock(s.s->unprocessed, 2); 
		p = s.s->unprocessed->rp; 
2002/0307    
		ensure(s, &s->unprocessed, 3); 
		s->unprocessed = pullupblock(s->unprocessed, 2); 
		p = s->unprocessed->rp; 
2001/0825    
		if(p[0] & 0x80){ 
			len = ((p[0] & 0x7f)<<8) | p[1]; 
1996/1029    
			ensure(s.s, &s.s->unprocessed, len); 
2002/0307    
			ensure(s, &s->unprocessed, len); 
1995/1217    
			pad = 0; 
2001/0825    
			toconsume = 2; 
1995/1217    
		} else { 
2002/0306    
			s.s->unprocessed = pullupblock(s.s->unprocessed, 3); 
2002/0307    
			s->unprocessed = pullupblock(s->unprocessed, 3); 
2001/0825    
			len = ((p[0] & 0x3f)<<8) | p[1]; 
			pad = p[2]; 
1996/1029    
			if(pad > len){ 
2002/0306/sys/src/9/port/devssl.c:584,5902002/0307/sys/src/9/port/devssl.c:585,591
1996/1029    
			} 
2001/0825    
			toconsume = 3; 
1995/1217    
		} 
2002/0306    
		ensure(s.s, &s.s->unprocessed, toconsume+len); 
2002/0307    
		ensure(s, &s->unprocessed, toconsume+len); 
1995/1217    
 
2001/0825    
		/* 
		 * Now we have a full SSL packet in the unprocessed list. 
2002/0306/sys/src/9/port/devssl.c:600,6602002/0307/sys/src/9/port/devssl.c:601,661
2001/0825    
		} 
 
		/* skip header */ 
		consume(&s.s->unprocessed, consumed, toconsume); 
2002/0307    
		consume(&s->unprocessed, consumed, toconsume); 
2001/0825    
 
2000/0913    
		/* grab the next message and decode/decrypt it */ 
2002/0306    
		b = qtake(&s.s->unprocessed, len, 0); 
2002/0307    
		b = qtake(&s->unprocessed, len, 0); 
2000/0913    
 
2002/0306    
		if(blocklen(b) != len) 
2001/0825    
			print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); 
 
1996/1029    
		if(waserror()){ 
			qunlock(&s.s->in.ctlq); 
2002/0307    
			qunlock(&s->in.ctlq); 
2000/0913    
			if(b != nil) 
				freeb(b); 
1996/1029    
			nexterror(); 
1995/1217    
		} 
1996/1029    
		qlock(&s.s->in.ctlq); 
		switch(s.s->state){ 
2002/0307    
		qlock(&s->in.ctlq); 
		switch(s->state){ 
1996/1029    
		case Sencrypting: 
2001/0825    
			if(b == nil) 
				error("ssl message too short (encrypting)"); 
2000/0913    
			b = decryptb(s.s, b); 
2002/0307    
			b = decryptb(s, b); 
1996/1029    
			break; 
		case Sdigesting: 
2000/0913    
			b = pullupblock(b, s.s->diglen); 
2002/0307    
			b = pullupblock(b, s->diglen); 
2000/0913    
			if(b == nil) 
2001/0825    
				error("ssl message too short (digesting)"); 
2000/0913    
			checkdigestb(s.s, b); 
			b->rp += s.s->diglen; 
2002/0307    
			checkdigestb(s, b); 
			b->rp += s->diglen; 
1996/1029    
			break; 
1997/0618    
		case Sdigenc: 
2000/0913    
			b = decryptb(s.s, b); 
			b = pullupblock(b, s.s->diglen); 
2002/0307    
			b = decryptb(s, b); 
			b = pullupblock(b, s->diglen); 
2000/0913    
			if(b == nil) 
2001/0825    
				error("ssl message too short (dig+enc)"); 
2000/0913    
			checkdigestb(s.s, b); 
			b->rp += s.s->diglen; 
1998/0501    
			len -= s.s->diglen; 
2002/0307    
			checkdigestb(s, b); 
			b->rp += s->diglen; 
			len -= s->diglen; 
1997/0618    
			break; 
1995/1218    
		} 
1995/1217    
 
		/* remove pad */ 
1996/1029    
		if(pad) 
2001/0602    
			s.s->processed = qtake(&b, len - pad, 1); 
2002/0307    
			s->processed = qtake(&b, len - pad, 1); 
2000/0913    
		else 
			s.s->processed = b; 
2002/0307    
			s->processed = b; 
2000/0913    
		b = nil; 
		s.s->in.mid++; 
		qunlock(&s.s->in.ctlq); 
2002/0307    
		s->in.mid++; 
		qunlock(&s->in.ctlq); 
2000/0913    
		poperror(); 
2001/0825    
		poperror(); 
1995/1217    
	} 
 
1996/1029    
	/* return at most what was asked for */ 
2001/0602    
	b = qtake(&s.s->processed, n, 0); 
2002/0307    
	b = qtake(&s->processed, n, 0); 
1995/1217    
 
1996/0531    
	qunlock(&s.s->in.q); 
2002/0307    
	qunlock(&s->in.q); 
1995/1217    
	poperror(); 
 
	return b; 
2002/0306/sys/src/9/port/devssl.c:663,6692002/0307/sys/src/9/port/devssl.c:664,670
1997/0327    
static long 
1998/0319    
sslread(Chan *c, void *a, long n, vlong off) 
1995/1213    
{ 
1996/0531    
	volatile struct { Block *b; } b; 
2002/0307    
	Block * volatile b; 
1996/1029    
	Block *nb; 
	uchar *va; 
	int i; 
2002/0306/sys/src/9/port/devssl.c:683,6892002/0307/sys/src/9/port/devssl.c:684,690
2001/0527    
		sprint(buf, "%d", ft); 
1996/1029    
		return readstr(offset, a, n, buf); 
	case Qdata: 
		b.b = sslbread(c, n, offset); 
2002/0307    
		b = sslbread(c, n, offset); 
1996/1029    
		break; 
1998/0417    
	case Qencalgs: 
		return readstr(offset, a, n, encalgs); 
2002/0306/sys/src/9/port/devssl.c:694,7122002/0307/sys/src/9/port/devssl.c:695,713
1995/1213    
	} 
 
1996/0223    
	if(waserror()){ 
1996/1029    
		freeblist(b.b); 
2002/0307    
		freeblist(b); 
1996/0223    
		nexterror(); 
1995/1213    
	} 
 
1996/1029    
	n = 0; 
	va = a; 
	for(nb = b.b; nb; nb = nb->next){ 
2002/0307    
	for(nb = b; nb; nb = nb->next){ 
1996/1029    
		i = BLEN(nb); 
		memmove(va+n, nb->rp, i); 
		n += i; 
	} 
1996/0223    
 
1996/1029    
	freeblist(b.b); 
2002/0307    
	freeblist(b); 
1996/0223    
	poperror(); 
 
1995/1213    
	return n; 
2002/0306/sys/src/9/port/devssl.c:723,7282002/0307/sys/src/9/port/devssl.c:724,759
1997/0618    
		*buf++ = nrand(256); 
1996/1029    
} 
 
2002/0307    
static long 
sslbwrite(Chan *c, Block *b, ulong) 
{ 
	Dstate * volatile s; 
	long rv; 
 
	s = dstate[CONV(c->qid)]; 
	if(s == nil) 
		panic("sslbwrite"); 
 
	if(s->state == Sincomplete){ 
		freeb(b); 
		error(Ebadusefd); 
	} 
 
	/* lock so split writes won't interleave */ 
	if(waserror()){ 
		qunlock(&s->out.q); 
		nexterror(); 
	} 
	qlock(&s->out.q); 
 
	rv = sslput(s, b); 
 
	poperror(); 
	qunlock(&s->out.q); 
 
	return rv; 
} 
 
1996/1029    
/* 
2000/0913    
 *  use SSL record format, add in count, digest and/or encrypt. 
 *  the write is interruptable.  if it is interrupted, we'll 
2002/0306/sys/src/9/port/devssl.c:730,7772002/0307/sys/src/9/port/devssl.c:761,796
2000/0913    
 *  it since we don't know if any bytes have been written. 
1995/1215    
 */ 
1997/0327    
static long 
1995/1215    
sslbwrite(Chan *c, Block *b, ulong offset) 
2002/0307    
sslput(Dstate *s, Block * volatile b) 
1995/1213    
{ 
1996/0531    
	volatile struct { Dstate *s; } s; 
	volatile struct { Block *b; } bb; 
1995/1213    
	Block *nb; 
1995/1215    
	int h, n, m, pad, rv; 
1995/1217    
	uchar *p; 
2002/0307    
	int offset; 
1995/1215    
 
1996/0531    
	bb.b = b; 
1996/1029    
	s.s = dstate[CONV(c->qid)]; 
	if(s.s == 0) 
		panic("sslbwrite"); 
	if(s.s->state == Sincomplete){ 
		freeb(b); 
1995/1215    
		error(Ebadusefd); 
1996/1029    
	} 
1995/1215    
                 
	if(waserror()){ 
1996/0531    
		qunlock(&s.s->out.q); 
2000/0913    
		if(bb.b != nil) 
1996/0531    
			freeb(bb.b); 
2002/0307    
		if(b != nil) 
			free(b); 
1995/1215    
		nexterror(); 
	} 
1996/0531    
	qlock(&s.s->out.q); 
1995/1215    
 
	rv = 0; 
1996/0531    
	while(bb.b){ 
		m = n = BLEN(bb.b); 
		h = s.s->diglen + 2; 
2002/0307    
	while(b != nil){ 
		m = n = BLEN(b); 
		h = s->diglen + 2; 
1995/1215    
 
1995/1218    
		/* trim to maximum block size */ 
1995/1215    
		pad = 0; 
1996/0531    
		if(m > s.s->max){ 
			m = s.s->max; 
		} else if(s.s->blocklen != 1){ 
1998/0501    
			pad = (m + s.s->diglen)%s.s->blocklen; 
2002/0307    
		if(m > s->max){ 
			m = s->max; 
		} else if(s->blocklen != 1){ 
			pad = (m + s->diglen)%s->blocklen; 
1995/1215    
			if(pad){ 
1996/0531    
				if(m > s.s->maxpad){ 
2002/0307    
				if(m > s->maxpad){ 
1995/1215    
					pad = 0; 
1996/0531    
					m = s.s->maxpad; 
2002/0307    
					m = s->maxpad; 
1995/1218    
				} else { 
1996/0531    
					pad = s.s->blocklen - pad; 
2002/0307    
					pad = s->blocklen - pad; 
1995/1218    
					h++; 
1995/1215    
				} 
			} 
2002/0306/sys/src/9/port/devssl.c:780,7942002/0307/sys/src/9/port/devssl.c:799,813
1995/1215    
		rv += m; 
		if(m != n){ 
			nb = allocb(m + h + pad); 
1996/0531    
			memmove(nb->wp + h, bb.b->rp, m); 
2002/0307    
			memmove(nb->wp + h, b->rp, m); 
1995/1215    
			nb->wp += m + h; 
1996/0531    
			bb.b->rp += m; 
2002/0307    
			b->rp += m; 
1995/1215    
		} else { 
1995/1218    
			/* add header space */ 
1996/0531    
			nb = padblock(bb.b, h); 
			bb.b = 0; 
2002/0307    
			nb = padblock(b, h); 
			b = 0; 
1995/1215    
		} 
1996/0531    
		m += s.s->diglen; 
2002/0307    
		m += s->diglen; 
1995/1215    
 
		/* SSL style count */ 
		if(pad){ 
2002/0306/sys/src/9/port/devssl.c:809,8362002/0307/sys/src/9/port/devssl.c:828,854
1995/1217    
			offset = 2; 
		} 
1995/1213    
 
1996/1029    
		switch(s.s->state){ 
2002/0307    
		switch(s->state){ 
1996/1029    
		case Sencrypting: 
1996/0531    
			nb = encryptb(s.s, nb, offset); 
2002/0307    
			nb = encryptb(s, nb, offset); 
1996/1029    
			break; 
		case Sdigesting: 
1996/0531    
			nb = digestb(s.s, nb, offset); 
2002/0307    
			nb = digestb(s, nb, offset); 
1996/1029    
			break; 
1997/0618    
		case Sdigenc: 
			nb = digestb(s.s, nb, offset); 
			nb = encryptb(s.s, nb, offset); 
2002/0307    
			nb = digestb(s, nb, offset); 
			nb = encryptb(s, nb, offset); 
1997/0618    
			break; 
1996/1029    
		} 
1995/1213    
 
1997/0618    
		s.s->out.mid++; 
2002/0307    
		s->out.mid++; 
1997/0618    
 
2001/0527    
		m = BLEN(nb); 
1997/0327    
		devtab[s.s->c->type]->bwrite(s.s->c, nb, s.s->c->offset); 
2001/0527    
		s.s->c->offset += m; 
2002/0307    
		devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); 
		s->c->offset += m; 
1995/1215    
	} 
1996/0531    
	qunlock(&s.s->out.q); 
1995/1215    
	poperror(); 
 
2002/0307    
	poperror(); 
1995/1215    
	return rv; 
1996/0223    
} 
 
2002/0306/sys/src/9/port/devssl.c:1033,10962002/0307/sys/src/9/port/devssl.c:1051,1123
1997/0618    
} 
 
1997/0327    
static long 
1998/0319    
sslwrite(Chan *c, void *a, long n, vlong off) 
2002/0307    
sslwrite(Chan *c, void *a, long n, vlong) 
1996/0223    
{ 
1996/1029    
	volatile struct { Dstate *s; } s; 
1996/0531    
	volatile struct { Block *b; } b; 
2002/0307    
	Dstate * volatile s; 
	Block * volatile b; 
1996/1029    
	int m, t; 
1999/0804    
	char *p, *np, *e, buf[128]; 
	uchar *x; 
1998/0319    
	ulong offset = off; 
1996/0223    
 
1996/1029    
	s.s = dstate[CONV(c->qid)]; 
	if(s.s == 0) 
2002/0307    
	s = dstate[CONV(c->qid)]; 
	if(s == 0) 
1996/1029    
		panic("sslwrite"); 
1996/0223    
 
1996/1029    
	t = TYPE(c->qid); 
	if(t == Qdata){ 
		if(s.s->state == Sincomplete) 
2002/0307    
		if(s->state == Sincomplete) 
1996/1029    
			error(Ebadusefd); 
1996/0223    
 
2002/0307    
		/* lock should a write gets split over multiple records */ 
		if(waserror()){ 
			qunlock(&s->out.q); 
			nexterror(); 
		} 
		qlock(&s->out.q); 
 
1996/0223    
		p = a; 
1996/1029    
		e = p + n; 
		do { 
1996/0223    
			m = e - p; 
1996/1029    
			if(m > s.s->max) 
				m = s.s->max; 
2002/0307    
			if(m > s->max) 
				m = s->max; 
1998/0512    
 
1996/0531    
			b.b = allocb(m); 
2002/0307    
			b = allocb(m); 
1996/0223    
			if(waserror()){ 
1996/0531    
				freeb(b.b); 
2002/0307    
				freeb(b); 
1996/0223    
				nexterror(); 
			} 
1996/0531    
			memmove(b.b->wp, p, m); 
2002/0307    
			memmove(b->wp, p, m); 
1996/0223    
			poperror(); 
1996/0531    
			b.b->wp += m; 
2002/0307    
			b->wp += m; 
1998/0512    
 
1996/0531    
			sslbwrite(c, b.b, offset); 
2002/0307    
			sslput(s, b); 
1996/1029    
 
			p += m; 
		} while(p < e); 
2002/0307    
 
		poperror(); 
		qunlock(&s->out.q); 
1996/1029    
		return n; 
	} 
 
	/* mutex with operations using what we're about to change */ 
	if(waserror()){ 
		qunlock(&s.s->in.ctlq); 
		qunlock(&s.s->out.q); 
2002/0307    
		qunlock(&s->in.ctlq); 
		qunlock(&s->out.q); 
1996/1029    
		nexterror(); 
	} 
	qlock(&s.s->in.ctlq); 
	qlock(&s.s->out.q); 
2002/0307    
	qlock(&s->in.ctlq); 
	qlock(&s->out.q); 
1996/1029    
 
	switch(t){ 
1996/0223    
	default: 
1996/1029    
		panic("sslwrite"); 
	case Qsecretin: 
		setsecret(&s.s->in, a, n); 
2002/0307    
		setsecret(&s->in, a, n); 
1996/1029    
		goto out; 
	case Qsecretout: 
		setsecret(&s.s->out, a, n); 
2002/0307    
		setsecret(&s->out, a, n); 
1996/1029    
		goto out; 
	case Qctl: 
		break; 
2002/0306/sys/src/9/port/devssl.c:1108,11452002/0307/sys/src/9/port/devssl.c:1135,1172
1996/1029    
		*p++ = 0; 
1995/1213    
 
1996/1029    
	if(strcmp(buf, "fd") == 0){ 
		s.s->c = buftochan(p); 
2002/0307    
		s->c = buftochan(p); 
1995/1213    
 
1996/1029    
		/* default is clear (msg delimiters only) */ 
		s.s->state = Sclear; 
		s.s->blocklen = 1; 
		s.s->diglen = 0; 
		s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; 
1997/0618    
		s.s->in.mid = 0; 
		s.s->out.mid = 0; 
2002/0307    
		s->state = Sclear; 
		s->blocklen = 1; 
		s->diglen = 0; 
		s->maxpad = s->max = (1<<15) - s->diglen - 1; 
		s->in.mid = 0; 
		s->out.mid = 0; 
1996/1029    
	} else if(strcmp(buf, "alg") == 0 && p != 0){ 
		s.s->blocklen = 1; 
		s.s->diglen = 0; 
2002/0307    
		s->blocklen = 1; 
		s->diglen = 0; 
1995/1213    
 
1996/1029    
		if(s.s->c == 0) 
2002/0307    
		if(s->c == 0) 
1996/1029    
			error("must set fd before algorithm"); 
 
1999/0527    
		s.s->state = Sclear; 
		s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; 
2002/0307    
		s->state = Sclear; 
		s->maxpad = s->max = (1<<15) - s->diglen - 1; 
1996/1029    
		if(strcmp(p, "clear") == 0){ 
			goto out; 
1995/1213    
		} 
 
1996/1029    
		if(s.s->in.secret && s.s->out.secret == 0) 
			setsecret(&s.s->out, s.s->in.secret, s.s->in.slen); 
		if(s.s->out.secret && s.s->in.secret == 0) 
			setsecret(&s.s->in, s.s->out.secret, s.s->out.slen); 
1997/0618    
		if(s.s->in.secret == 0 || s.s->out.secret == 0) 
2002/0307    
		if(s->in.secret && s->out.secret == 0) 
			setsecret(&s->out, s->in.secret, s->in.slen); 
		if(s->out.secret && s->in.secret == 0) 
			setsecret(&s->in, s->out.secret, s->out.slen); 
		if(s->in.secret == 0 || s->out.secret == 0) 
1997/0618    
			error("algorithm but no secret"); 
 
		s.s->hf = 0; 
		s.s->encryptalg = Noencryption; 
		s.s->blocklen = 1; 
2002/0307    
		s->hf = 0; 
		s->encryptalg = Noencryption; 
		s->blocklen = 1; 
1997/0618    
 
		for(;;){ 
			np = strchr(p, ' '); 
2002/0306/sys/src/9/port/devssl.c:1146,11532002/0307/sys/src/9/port/devssl.c:1173,1180
1997/0618    
			if(np) 
				*np++ = 0; 
 
			if(parsehashalg(p, s.s) < 0) 
			if(parseencryptalg(p, s.s) < 0) 
2002/0307    
			if(parsehashalg(p, s) < 0) 
			if(parseencryptalg(p, s) < 0) 
1999/0804    
				error("bad algorithm"); 
1997/0618    
 
			if(np == 0) 
2002/0306/sys/src/9/port/devssl.c:1155,11882002/0307/sys/src/9/port/devssl.c:1182,1215
1997/0618    
			p = np; 
		} 
 
		if(s.s->hf == 0 && s.s->encryptalg == Noencryption) 
2002/0307    
		if(s->hf == 0 && s->encryptalg == Noencryption) 
1999/0804    
			error("bad algorithm"); 
1995/1213    
 
1996/1029    
		if(s.s->blocklen != 1){ 
			s.s->max = (1<<15) - s.s->diglen - 1; 
			s.s->max -= s.s->max % s.s->blocklen; 
			s.s->maxpad = (1<<14) - s.s->diglen - 1; 
			s.s->maxpad -= s.s->maxpad % s.s->blocklen; 
2002/0307    
		if(s->blocklen != 1){ 
			s->max = (1<<15) - s->diglen - 1; 
			s->max -= s->max % s->blocklen; 
			s->maxpad = (1<<14) - s->diglen - 1; 
			s->maxpad -= s->maxpad % s->blocklen; 
1996/1029    
		} else 
			s.s->maxpad = s.s->max = (1<<15) - s.s->diglen - 1; 
2002/0307    
			s->maxpad = s->max = (1<<15) - s->diglen - 1; 
1999/0804    
	} else if(strcmp(buf, "secretin") == 0 && p != 0) { 
		m = (strlen(p)*3)/2; 
		x = smalloc(m); 
2002/0306    
		t = dec64(x, m, p, strlen(p)); 
		setsecret(&s.s->in, x, t); 
2002/0307    
		setsecret(&s->in, x, t); 
1999/0804    
		free(x); 
	} else if(strcmp(buf, "secretout") == 0 && p != 0) { 
		m = (strlen(p)*3)/2 + 1; 
		x = smalloc(m); 
2002/0306    
		t = dec64(x, m, p, strlen(p)); 
		setsecret(&s.s->out, x, t); 
2002/0307    
		setsecret(&s->out, x, t); 
1999/0804    
		free(x); 
1996/1029    
	} else 
		error(Ebadarg); 
1995/1213    
 
1996/1029    
out: 
	qunlock(&s.s->in.ctlq); 
	qunlock(&s.s->out.q); 
2002/0307    
	qunlock(&s->in.ctlq); 
	qunlock(&s->out.q); 
1996/1029    
	poperror(); 
	return n; 
1998/0417    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)