Beispiel #1
0
int
main(int argc, char *argv[])
{

	char inp[UCHAR_MAX + 1];
	char out[4 * UCHAR_MAX + 1];
	int i, j, fail = 0;
	ssize_t owant, o, r;

	for (i = 0; i <= UCHAR_MAX; i++) {
		inp[i] = i;
	}
	strvisx(out, inp, UCHAR_MAX + 1, 0);
	printf("%s\n", out);

	for (i = 0; i < NTESTS; i++) {
		arc4random_buf(ibuf, sizeof(ibuf) - 1);
		ibuf[sizeof(ibuf) - 1] = '\0';
		title = 0;

		for (j = 0; j < sizeof(flags)/sizeof(flags[0]); j++) {
			owant = sizeof(ibuf);
			o = strnvis(obuf, ibuf, owant, flags[j]);
			if (o >= owant) {
				owant = o + 1;
				o = strnvis(obuf, ibuf, owant, flags[j]);
				if (o > owant) {
					dotitle(i, j);
					printf("HUGE overflow\n");
				}
				if (o < owant - 1) {
					dotitle(i, j);
					printf("over-estimate of overflow\n");
				}
			} else if (o > strlen(ibuf) * 4) {
				dotitle(i, j);
				printf("wants too much %d %d\n", o, strlen(ibuf) * 4);
				continue;
			}

			r = strnunvis(rbuf, obuf, sizeof rbuf);

			if (r == -1) {
				dotitle(i, j);
				printf("cannot decode\n");
				printf("%s\n", obuf);
				fail = 1;
			} else if (r != strlen(ibuf)) {
				dotitle(i, j);
				printf("rlen %d != inlen %d\n", r, strlen(ibuf));
				printf("%s\n", obuf);
				printf("%s\n", rbuf);
				fail = 1;
			} else if (bcmp(ibuf, rbuf, r)) {
				dotitle(i, j);
				printf("strings are different\n");
				printf("%s\n", ibuf);
				printf("%s\n", rbuf);
				fail = 1;
			}
		}
	}
	exit(fail);
}
Beispiel #2
0
int
mbrinit(cdev_t dev, struct disk_info *info, struct diskslices **sspp)
{
	struct buf *bp;
	u_char	*cp;
	int	dospart;
	struct dos_partition *dp;
	struct dos_partition *dp0;
	struct dos_partition dpcopy[NDOSPART];
	int	error;
	int	max_ncyls;
	int	max_nsectors;
	int	max_ntracks;
	u_int64_t mbr_offset;
	char	partname[2];
	u_long	secpercyl;
	char	*sname = "tempname";
	struct diskslice *sp;
	struct diskslices *ssp;
	cdev_t wdev;

	mbr_offset = DOSBBSECTOR;
reread_mbr:
	/*
	 * Don't bother if the block size is weird or the
	 * media size is 0 (probably means no media present).
	 */
	if (info->d_media_blksize & DEV_BMASK)
		return (EIO);
	if (info->d_media_size == 0)
		return (EIO);

	/*
	 * Read master boot record.
	 */
	wdev = dev;
	bp = geteblk((int)info->d_media_blksize);
	bp->b_bio1.bio_offset = (off_t)mbr_offset * info->d_media_blksize;
	bp->b_bio1.bio_done = biodone_sync;
	bp->b_bio1.bio_flags |= BIO_SYNC;
	bp->b_bcount = info->d_media_blksize;
	bp->b_cmd = BUF_CMD_READ;
	bp->b_flags |= B_FAILONDIS;
	dev_dstrategy(wdev, &bp->b_bio1);
	if (biowait(&bp->b_bio1, "mbrrd") != 0) {
		if ((info->d_dsflags & DSO_MBRQUIET) == 0) {
			diskerr(&bp->b_bio1, wdev,
				"reading primary partition table: error",
				LOG_PRINTF, 0);
			kprintf("\n");
		}
		error = EIO;
		goto done;
	}

	/* Weakly verify it. */
	cp = bp->b_data;
	sname = dsname(dev, 0, 0, 0, NULL);
	if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
		if (bootverbose)
			kprintf("%s: invalid primary partition table: no magic\n",
			       sname);
		error = EINVAL;
		goto done;
	}

	/* Make a copy of the partition table to avoid alignment problems. */
	memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));

	dp0 = &dpcopy[0];

	/*
	 * Check for "Ontrack Diskmanager" or GPT.  If a GPT is found in
	 * the first dos partition, ignore the rest of the MBR and go
	 * to GPT processing.
	 */
	for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
		if (dospart == 0 &&
		    (dp->dp_typ == DOSPTYP_PMBR || dp->dp_typ == DOSPTYP_GPT)) {
			if (bootverbose)
				kprintf(
	    "%s: Found GPT in slice #%d\n", sname, dospart + 1);
			error = gptinit(dev, info, sspp);
			goto done;
		}

		if (dp->dp_typ == DOSPTYP_ONTRACK) {
			if (bootverbose)
				kprintf(
	    "%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
			bp->b_flags |= B_INVAL | B_AGE;
			brelse(bp);
			mbr_offset = 63;
			goto reread_mbr;
		}
	}

	if (bcmp(dp0, historical_bogus_partition_table,
		 sizeof historical_bogus_partition_table) == 0 ||
	    bcmp(dp0, historical_bogus_partition_table_fixed,
		 sizeof historical_bogus_partition_table_fixed) == 0) {
#if 0
		TRACE(("%s: invalid primary partition table: historical\n",
		       sname));
#endif /* 0 */
		if (bootverbose)
			kprintf(
     "%s: invalid primary partition table: Dangerously Dedicated (ignored)\n",
			       sname);
		error = EINVAL;
		goto done;
	}

	/* Guess the geometry. */
	/*
	 * TODO:
	 * Perhaps skip entries with 0 size.
	 * Perhaps only look at entries of type DOSPTYP_386BSD.
	 */
	max_ncyls = 0;
	max_nsectors = 0;
	max_ntracks = 0;
	for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
		int	ncyls;
		int	nsectors;
		int	ntracks;

		ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
		if (max_ncyls < ncyls)
			max_ncyls = ncyls;
		nsectors = DPSECT(dp->dp_esect);
		if (max_nsectors < nsectors)
			max_nsectors = nsectors;
		ntracks = dp->dp_ehd + 1;
		if (max_ntracks < ntracks)
			max_ntracks = ntracks;
	}

	/*
	 * Check that we have guessed the geometry right by checking the
	 * partition entries.
	 */
	/*
	 * TODO:
	 * As above.
	 * Check for overlaps.
	 * Check against d_secperunit if the latter is reliable.
	 */
	error = 0;
	for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
		if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
		    && dp->dp_start == 0 && dp->dp_size == 0)
			continue;
		//sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
		//	       WHOLE_SLICE_PART, partname);

		/*
		 * Temporarily ignore errors from this check.  We could
		 * simplify things by accepting the table eariler if we
		 * always ignore errors here.  Perhaps we should always
		 * accept the table if the magic is right but not let
		 * bad entries affect the geometry.
		 */
		check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
			   mbr_offset);
	}
	if (error != 0)
		goto done;

	/*
	 * Accept the DOS partition table.
	 *
	 * Adjust the disk information structure with updated CHS
	 * conversion parameters, but only use values extracted from
	 * the primary partition table.
	 *
	 * NOTE!  Regardless of our having to deal with this old cruft,
	 * we do not screw around with the info->d_media* parameters.
	 */
	secpercyl = (u_long)max_nsectors * max_ntracks;
	if (secpercyl != 0 && mbr_offset == DOSBBSECTOR) {
		info->d_secpertrack = max_nsectors;
		info->d_nheads = max_ntracks;
		info->d_secpercyl = secpercyl;
		info->d_ncylinders = info->d_media_blocks / secpercyl;
	}

	/*
	 * We are passed a pointer to a suitably initialized minimal
	 * slices "struct" with no dangling pointers in it.  Replace it
	 * by a maximal one.  This usually oversizes the "struct", but
	 * enlarging it while searching for logical drives would be
	 * inconvenient.
	 */
	kfree(*sspp, M_DEVBUF);
	ssp = dsmakeslicestruct(MAX_SLICES, info);
	*sspp = ssp;

	/* Initialize normal slices. */
	sp = &ssp->dss_slices[BASE_SLICE];
	for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
		sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
			       WHOLE_SLICE_PART, partname);
		(void)mbr_setslice(sname, info, sp, dp, mbr_offset);
	}
	ssp->dss_nslices = BASE_SLICE + NDOSPART;

	/* Handle extended partitions. */
	sp -= NDOSPART;
	for (dospart = 0; dospart < NDOSPART; dospart++, sp++) {
		if (sp->ds_type == DOSPTYP_EXTENDED ||
		    sp->ds_type == DOSPTYP_EXTENDEDX) {
			mbr_extended(wdev, info, ssp,
				     sp->ds_offset, sp->ds_size, sp->ds_offset,
				     max_nsectors, max_ntracks, mbr_offset, 1);
		}
	}

	/*
	 * mbr_extended() abuses ssp->dss_nslices for the number of slices
	 * that would be found if there were no limit on the number of slices
	 * in *ssp.  Cut it back now.
	 */
	if (ssp->dss_nslices > MAX_SLICES)
		ssp->dss_nslices = MAX_SLICES;

done:
	bp->b_flags |= B_INVAL | B_AGE;
	brelse(bp);
	if (error == EINVAL)
		error = 0;
	return (error);
}
static int
wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
		       const unsigned char *addr, int key_idx, int set_tx,
		       const u8 *seq, size_t seq_len,
		       const u8 *key, size_t key_len)
{
	struct wpa_driver_bsd_data *drv = priv;
	struct ieee80211req_key wk;
	struct ether_addr ea;
	char *alg_name;
	u_int8_t cipher;

	if (alg == WPA_ALG_NONE)
		return wpa_driver_bsd_del_key(drv, key_idx, addr);

	switch (alg) {
	case WPA_ALG_WEP:
		alg_name = "WEP";
		cipher = IEEE80211_CIPHER_WEP;
		break;
	case WPA_ALG_TKIP:
		alg_name = "TKIP";
		cipher = IEEE80211_CIPHER_TKIP;
		break;
	case WPA_ALG_CCMP:
		alg_name = "CCMP";
		cipher = IEEE80211_CIPHER_AES_CCM;
		break;
	default:
		wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
			__func__, alg);
		return -1;
	}

	memcpy(&ea, addr, IEEE80211_ADDR_LEN);
	wpa_printf(MSG_DEBUG,
		"%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
		__func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
		seq_len, key_len);

	if (seq_len > sizeof(u_int64_t)) {
		wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
			__func__, seq_len);
		return -2;
	}
	if (key_len > sizeof(wk.ik_keydata)) {
		wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
			__func__, key_len);
		return -3;
	}

	memset(&wk, 0, sizeof(wk));
	wk.ik_type = cipher;
	wk.ik_flags = IEEE80211_KEY_RECV;
	if (set_tx)
		wk.ik_flags |= IEEE80211_KEY_XMIT;
	memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
	/*
	 * Deduce whether group/global or unicast key by checking
	 * the address (yech).  Note also that we can only mark global
	 * keys default; doing this for a unicast key is an error.
	 */
	if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
		wk.ik_flags |= IEEE80211_KEY_GROUP;
		wk.ik_keyix = key_idx;
	} else {
		wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
	}
	if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
	wk.ik_keylen = key_len;
	memcpy(&wk.ik_keyrsc, seq, seq_len);
	memcpy(wk.ik_keydata, key, key_len);

	return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
}
Beispiel #4
0
int
ng_l2cap_l2ca_cfg_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_l2cap_l2ca_cfg_ip	*ip = NULL;
	ng_l2cap_chan_p		 ch = NULL;
	ng_l2cap_cmd_p		 cmd = NULL;
	struct mbuf		*opt = NULL;
        u_int16_t		*mtu = NULL, *flush_timo = NULL;
        ng_l2cap_flow_p		 flow = NULL;
	int			 error = 0;

	/* Check message */
	if (msg->header.arglen != sizeof(*ip)) {
		NG_L2CAP_ALERT(
"%s: %s - Invalid L2CA_Config request message size, size=%d\n",
			__func__, NG_NODE_NAME(l2cap->node),
			msg->header.arglen);
		error = EMSGSIZE;
		goto out;
	}

	ip = (ng_l2cap_l2ca_cfg_ip *)(msg->data);

	/* Check if we have this channel */
	ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid, NG_L2CAP_L2CA_IDTYPE_BREDR);
	if (ch == NULL) {
		NG_L2CAP_ERR(
"%s: %s - unexpected L2CA_Config request message. " \
"Channel does not exist, lcid=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ip->lcid);
		error = ENOENT;
		goto out;
	}

	/* Check channel state */
	if (ch->state != NG_L2CAP_OPEN && ch->state != NG_L2CAP_CONFIG) {
		NG_L2CAP_ERR(
"%s: %s - unexpected L2CA_Config request message. " \
"Invalid channel state, state=%d, lcid=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->state,
			ch->scid);
		error = EINVAL;
		goto out;
	}

	/* Set requested channel configuration options */
	ch->imtu = ip->imtu;
	bcopy(&ip->oflow, &ch->oflow, sizeof(ch->oflow));
	ch->flush_timo = ip->flush_timo;
	ch->link_timo = ip->link_timo;

	/* Compare channel settings with defaults */
	if (ch->imtu != NG_L2CAP_MTU_DEFAULT)
		mtu = &ch->imtu;
	if (ch->flush_timo != NG_L2CAP_FLUSH_TIMO_DEFAULT)
		flush_timo = &ch->flush_timo;
	if (bcmp(ng_l2cap_default_flow(), &ch->oflow, sizeof(ch->oflow)) != 0)
		flow = &ch->oflow;

	/* Create configuration options */
	_ng_l2cap_build_cfg_options(opt, mtu, flush_timo, flow);
	if (opt == NULL) {
                error = ENOBUFS;
		goto out;
	}

	/* Create L2CAP command descriptor */
	cmd = ng_l2cap_new_cmd(ch->con, ch, ng_l2cap_get_ident(ch->con),
			NG_L2CAP_CFG_REQ, msg->header.token);
	if (cmd == NULL) {
		NG_FREE_M(opt);
		error = ENOMEM;
		goto out;
	}

	if (cmd->ident == NG_L2CAP_NULL_IDENT) {
		ng_l2cap_free_cmd(cmd);
		NG_FREE_M(opt);
		error = EIO;
		goto out;
	}

	/* Create L2CAP command packet */
	_ng_l2cap_cfg_req(cmd->aux, cmd->ident, ch->dcid, 0, opt);
	if (cmd->aux == NULL) {
		ng_l2cap_free_cmd(cmd);
		error =  ENOBUFS;
		goto out;
	}

	/* Adjust channel state for re-configuration */
	if (ch->state == NG_L2CAP_OPEN) {
		ch->state = (ch->scid == NG_L2CAP_ATT_CID)?
			NG_L2CAP_OPEN : NG_L2CAP_CONFIG;
		ch->cfg_state = 0;
	}

        /* Link command to the queue */
	ng_l2cap_link_cmd(ch->con, cmd);
	ng_l2cap_lp_deliver(ch->con);
out:
	return (error);
} /* ng_l2cap_l2ca_cfg_req */
Beispiel #5
0
int
main(int argc, char **argv)
{

    int         dec_ind;	/* current indentation for declarations */
    int         di_stack[20];	/* a stack of structure indentation levels */
    int         flushed_nl;	/* used when buffering up comments to remember
				 * that a newline was passed over */
    int         force_nl;	/* when true, code must be broken */
    int         hd_type = 0;	/* used to store type of stmt for if (...),
				 * for (...), etc */
    int		i;		/* local loop counter */
    int         scase;		/* set to true when we see a case, so we will
				 * know what to do with the following colon */
    int         sp_sw;		/* when true, we are in the expression of
				 * if(...), while(...), etc. */
    int         squest;		/* when this is positive, we have seen a ?
				 * without the matching : in a <c>?<s>:<s>
				 * construct */
    const char *t_ptr;		/* used for copying tokens */
    int		tabs_to_var;	/* true if using tabs to indent to var name */
    int         type_code;	/* the type of token, returned by lexi */

    int         last_else = 0;	/* true iff last keyword was an else */


    /*-----------------------------------------------*\
    |		      INITIALIZATION		      |
    \*-----------------------------------------------*/

    found_err = 0;

    ps.p_stack[0] = stmt;	/* this is the parser's stack */
    ps.last_nl = true;		/* this is true if the last thing scanned was
				 * a newline */
    ps.last_token = semicolon;
    combuf = (char *) malloc(bufsize);
    if (combuf == NULL)
	err(1, NULL);
    labbuf = (char *) malloc(bufsize);
    if (labbuf == NULL)
	err(1, NULL);
    codebuf = (char *) malloc(bufsize);
    if (codebuf == NULL)
	err(1, NULL);
    tokenbuf = (char *) malloc(bufsize);
    if (tokenbuf == NULL)
	err(1, NULL);
    l_com = combuf + bufsize - 5;
    l_lab = labbuf + bufsize - 5;
    l_code = codebuf + bufsize - 5;
    l_token = tokenbuf + bufsize - 5;
    combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label, and
						 * comment buffers */
    combuf[1] = codebuf[1] = labbuf[1] = '\0';
    ps.else_if = 1;		/* Default else-if special processing to on */
    s_lab = e_lab = labbuf + 1;
    s_code = e_code = codebuf + 1;
    s_com = e_com = combuf + 1;
    s_token = e_token = tokenbuf + 1;

    in_buffer = (char *) malloc(10);
    if (in_buffer == NULL)
	err(1, NULL);
    in_buffer_limit = in_buffer + 8;
    buf_ptr = buf_end = in_buffer;
    line_no = 1;
    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
    sp_sw = force_nl = false;
    ps.in_or_st = false;
    ps.bl_line = true;
    dec_ind = 0;
    di_stack[ps.dec_nest = 0] = 0;
    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;

    scase = ps.pcase = false;
    squest = 0;
    sc_end = 0;
    bp_save = 0;
    be_save = 0;

    output = 0;
    tabs_to_var = 0;

    /*--------------------------------------------------*\
    |   		COMMAND LINE SCAN		 |
    \*--------------------------------------------------*/

#ifdef undef
    max_col = 78;		/* -l78 */
    lineup_to_parens = 1;	/* -lp */
    ps.ljust_decl = 0;		/* -ndj */
    ps.com_ind = 33;		/* -c33 */
    star_comment_cont = 1;	/* -sc */
    ps.ind_size = 8;		/* -i8 */
    verbose = 0;
    ps.decl_indent = 16;	/* -di16 */
    ps.local_decl_indent = -1;	/* if this is not set to some nonnegative value
				 * by an arg, we will set this equal to
				 * ps.decl_ind */
    ps.indent_parameters = 1;	/* -ip */
    ps.decl_com_ind = 0;	/* if this is not set to some positive value
				 * by an arg, we will set this equal to
				 * ps.com_ind */
    btype_2 = 1;		/* -br */
    cuddle_else = 1;		/* -ce */
    ps.unindent_displace = 0;	/* -d0 */
    ps.case_indent = 0;		/* -cli0 */
    format_block_comments = 1;	/* -fcb */
    format_col1_comments = 1;	/* -fc1 */
    procnames_start_line = 1;	/* -psl */
    proc_calls_space = 0;	/* -npcs */
    comment_delimiter_on_blankline = 1;	/* -cdb */
    ps.leave_comma = 1;		/* -nbc */
#endif

    for (i = 1; i < argc; ++i)
	if (strcmp(argv[i], "-npro") == 0)
	    break;
    set_defaults();
    if (i >= argc)
	set_profile();

    for (i = 1; i < argc; ++i) {

	/*
	 * look thru args (if any) for changes to defaults
	 */
	if (argv[i][0] != '-') {/* no flag on parameter */
	    if (input == NULL) {	/* we must have the input file */
		in_name = argv[i];	/* remember name of input file */
		input = fopen(in_name, "r");
		if (input == NULL)	/* check for open error */
			err(1, "%s", in_name);
		continue;
	    }
	    else if (output == NULL) {	/* we have the output file */
		out_name = argv[i];	/* remember name of output file */
		if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
							 * the file */
		    errx(1, "input and output files must be different");
		}
		output = fopen(out_name, "w");
		if (output == NULL)	/* check for create error */
			err(1, "%s", out_name);
		continue;
	    }
	    errx(1, "unknown parameter: %s", argv[i]);
	}
	else
	    set_option(argv[i]);
    }				/* end of for */
    if (input == NULL)
	input = stdin;
    if (output == NULL) {
	if (troff || input == stdin)
	    output = stdout;
	else {
	    out_name = in_name;
	    bakcopy();
	}
    }
    if (ps.com_ind <= 1)
	ps.com_ind = 2;		/* dont put normal comments before column 2 */
    if (troff) {
	if (bodyf.font[0] == 0)
	    parsefont(&bodyf, "R");
	if (scomf.font[0] == 0)
	    parsefont(&scomf, "I");
	if (blkcomf.font[0] == 0)
	    blkcomf = scomf, blkcomf.size += 2;
	if (boxcomf.font[0] == 0)
	    boxcomf = blkcomf;
	if (stringf.font[0] == 0)
	    parsefont(&stringf, "L");
	if (keywordf.font[0] == 0)
	    parsefont(&keywordf, "B");
	writefdef(&bodyf, 'B');
	writefdef(&scomf, 'C');
	writefdef(&blkcomf, 'L');
	writefdef(&boxcomf, 'X');
	writefdef(&stringf, 'S');
	writefdef(&keywordf, 'K');
    }
    if (block_comment_max_col <= 0)
	block_comment_max_col = max_col;
    if (ps.local_decl_indent < 0)	/* if not specified by user, set this */
	ps.local_decl_indent = ps.decl_indent;
    if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
	ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
    if (continuation_indent == 0)
	continuation_indent = ps.ind_size;
    fill_buffer();		/* get first batch of stuff into input buffer */

    parse(semicolon);
    {
	char *p = buf_ptr;
	int col = 1;

	while (1) {
	    if (*p == ' ')
		col++;
	    else if (*p == '\t')
		col = ((col - 1) & ~7) + 9;
	    else
		break;
	    p++;
	}
	if (col > ps.ind_size)
	    ps.ind_level = ps.i_l_follow = col / ps.ind_size;
    }
    if (troff) {
	const char *p = in_name,
	           *beg = in_name;

	while (*p)
	    if (*p++ == '/')
		beg = p;
	fprintf(output, ".Fn \"%s\"\n", beg);
    }
    /*
     * START OF MAIN LOOP
     */

    while (1) {			/* this is the main loop.  it will go until we
				 * reach eof */
	int         is_procname;

	type_code = lexi();	/* lexi reads one token.  The actual
				 * characters read are stored in "token". lexi
				 * returns a code indicating the type of token */
	is_procname = ps.procname[0];

	/*
	 * The following code moves everything following an if (), while (),
	 * else, etc. up to the start of the following stmt to a buffer. This
	 * allows proper handling of both kinds of brace placement.
	 */

	flushed_nl = false;
	while (ps.search_brace) {	/* if we scanned an if(), while(),
					 * etc., we might need to copy stuff
					 * into a buffer we must loop, copying
					 * stuff into save_com, until we find
					 * the start of the stmt which follows
					 * the if, or whatever */
	    switch (type_code) {
	    case newline:
		++line_no;
		flushed_nl = true;
	    case form_feed:
		break;		/* form feeds and newlines found here will be
				 * ignored */

	    case lbrace:	/* this is a brace that starts the compound
				 * stmt */
		if (sc_end == 0) {	/* ignore buffering if a comment wasn't
					 * stored up */
		    ps.search_brace = false;
		    goto check_type;
		}
		if (btype_2) {
		    save_com[0] = '{';	/* we either want to put the brace
					 * right after the if */
		    goto sw_buffer;	/* go to common code to get out of
					 * this loop */
		}
	    case comment:	/* we have a comment, so we must copy it into
				 * the buffer */
		if (!flushed_nl || sc_end != 0) {
		    if (sc_end == 0) {	/* if this is the first comment, we
					 * must set up the buffer */
			save_com[0] = save_com[1] = ' ';
			sc_end = &(save_com[2]);
		    }
		    else {
			*sc_end++ = '\n';	/* add newline between
						 * comments */
			*sc_end++ = ' ';
			--line_no;
		    }
		    *sc_end++ = '/';	/* copy in start of comment */
		    *sc_end++ = '*';

		    for (;;) {	/* loop until we get to the end of the comment */
			*sc_end = *buf_ptr++;
			if (buf_ptr >= buf_end)
			    fill_buffer();

			if (*sc_end++ == '*' && *buf_ptr == '/')
			    break;	/* we are at end of comment */

			if (sc_end >= &(save_com[sc_size])) {	/* check for temp buffer
								 * overflow */
			    diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
			    fflush(output);
			    exit(1);
			}
		    }
		    *sc_end++ = '/';	/* add ending slash */
		    if (++buf_ptr >= buf_end)	/* get past / in buffer */
			fill_buffer();
		    break;
		}
	    default:		/* it is the start of a normal statement */
		if (flushed_nl)	/* if we flushed a newline, make sure it is
				 * put back */
		    force_nl = true;
		if ((type_code == sp_paren && *token == 'i'
			&& last_else && ps.else_if)
			|| (type_code == sp_nparen && *token == 'e'
			&& e_code != s_code && e_code[-1] == '}'))
		    force_nl = false;

		if (sc_end == 0) {	/* ignore buffering if comment wasn't
					 * saved up */
		    ps.search_brace = false;
		    goto check_type;
		}
		if (force_nl) {	/* if we should insert a nl here, put it into
				 * the buffer */
		    force_nl = false;
		    --line_no;	/* this will be re-increased when the nl is
				 * read from the buffer */
		    *sc_end++ = '\n';
		    *sc_end++ = ' ';
		    if (verbose && !flushed_nl)	/* print error msg if the line
						 * was not already broken */
			diag2(0, "Line broken");
		    flushed_nl = false;
		}
		for (t_ptr = token; *t_ptr; ++t_ptr)
		    *sc_end++ = *t_ptr;	/* copy token into temp buffer */
		ps.procname[0] = 0;

	sw_buffer:
		ps.search_brace = false;	/* stop looking for start of
						 * stmt */
		bp_save = buf_ptr;	/* save current input buffer */
		be_save = buf_end;
		buf_ptr = save_com;	/* fix so that subsequent calls to
					 * lexi will take tokens out of
					 * save_com */
		*sc_end++ = ' ';/* add trailing blank, just in case */
		buf_end = sc_end;
		sc_end = 0;
		break;
	    }			/* end of switch */
	    if (type_code != 0)	/* we must make this check, just in case there
				 * was an unexpected EOF */
		type_code = lexi();	/* read another token */
	    /* if (ps.search_brace) ps.procname[0] = 0; */
	    if ((is_procname = ps.procname[0]) && flushed_nl
		    && !procnames_start_line && ps.in_decl
		    && type_code == ident)
		flushed_nl = 0;
	}			/* end of while (search_brace) */
	last_else = 0;
check_type:
	if (type_code == 0) {	/* we got eof */
	    if (s_lab != e_lab || s_code != e_code
		    || s_com != e_com)	/* must dump end of line */
		dump_line();
	    if (ps.tos > 1)	/* check for balanced braces */
		diag2(1, "Stuff missing from end of file");

	    if (verbose) {
		printf("There were %d output lines and %d comments\n",
		       ps.out_lines, ps.out_coms);
		printf("(Lines with comments)/(Lines with code): %6.3f\n",
		       (1.0 * ps.com_lines) / code_lines);
	    }
	    fflush(output);
	    exit(found_err);
	}
	if (
		(type_code != comment) &&
		(type_code != newline) &&
		(type_code != preesc) &&
		(type_code != form_feed)) {
	    if (force_nl &&
		    (type_code != semicolon) &&
		    (type_code != lbrace || !btype_2)) {
		/* we should force a broken line here */
		if (verbose && !flushed_nl)
		    diag2(0, "Line broken");
		flushed_nl = false;
		dump_line();
		ps.want_blank = false;	/* dont insert blank at line start */
		force_nl = false;
	    }
	    ps.in_stmt = true;	/* turn on flag which causes an extra level of
				 * indentation. this is turned off by a ; or
				 * '}' */
	    if (s_com != e_com) {	/* the turkey has embedded a comment
					 * in a line. fix it */
		*e_code++ = ' ';
		for (t_ptr = s_com; *t_ptr; ++t_ptr) {
		    CHECK_SIZE_CODE;
		    *e_code++ = *t_ptr;
		}
		*e_code++ = ' ';
		*e_code = '\0';	/* null terminate code sect */
		ps.want_blank = false;
		e_com = s_com;
	    }
	}
	else if (type_code != comment)	/* preserve force_nl thru a comment */
	    force_nl = false;	/* cancel forced newline after newline, form
				 * feed, etc */



	/*-----------------------------------------------------*\
	|	   do switch on type of token scanned		|
	\*-----------------------------------------------------*/
	CHECK_SIZE_CODE;
	switch (type_code) {	/* now, decide what to do with the token */

	case form_feed:	/* found a form feed in line */
	    ps.use_ff = true;	/* a form feed is treated much like a newline */
	    dump_line();
	    ps.want_blank = false;
	    break;

	case newline:
	    if (ps.last_token != comma || ps.p_l_follow > 0
		    || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
		dump_line();
		ps.want_blank = false;
	    }
	    ++line_no;		/* keep track of input line number */
	    break;

	case lparen:		/* got a '(' or '[' */
	    ++ps.p_l_follow;	/* count parens to make Healy happy */
	    if (ps.want_blank && *token != '[' &&
		    (ps.last_token != ident || proc_calls_space
	      || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
		*e_code++ = ' ';
	    if (ps.in_decl && !ps.block_init)
		if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
		    ps.dumped_decl_indent = 1;
		    sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
		    e_code += strlen(e_code);
		}
		else {
		    while ((e_code - s_code) < dec_ind) {
			CHECK_SIZE_CODE;
			*e_code++ = ' ';
		    }
		    *e_code++ = token[0];
		}
	    else
		*e_code++ = token[0];
	    ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
	    if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
		    && ps.paren_indents[0] < 2 * ps.ind_size)
		ps.paren_indents[0] = 2 * ps.ind_size;
	    ps.want_blank = false;
	    if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
		/*
		 * this is a kluge to make sure that declarations will be
		 * aligned right if proc decl has an explicit type on it, i.e.
		 * "int a(x) {..."
		 */
		parse(semicolon);	/* I said this was a kluge... */
		ps.in_or_st = false;	/* turn off flag for structure decl or
					 * initialization */
	    }
	    if (ps.sizeof_keyword)
		ps.sizeof_mask |= 1 << ps.p_l_follow;
	    break;

	case rparen:		/* got a ')' or ']' */
	    rparen_count--;
	    if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
		ps.last_u_d = true;
		ps.cast_mask &= (1 << ps.p_l_follow) - 1;
		ps.want_blank = false;
	    } else
		ps.want_blank = true;
	    ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
	    if (--ps.p_l_follow < 0) {
		ps.p_l_follow = 0;
		diag3(0, "Extra %c", *token);
	    }
	    if (e_code == s_code)	/* if the paren starts the line */
		ps.paren_level = ps.p_l_follow;	/* then indent it */

	    *e_code++ = token[0];

	    if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
							 * (...), or some such */
		sp_sw = false;
		force_nl = true;/* must force newline after if */
		ps.last_u_d = true;	/* inform lexi that a following
					 * operator is unary */
		ps.in_stmt = false;	/* dont use stmt continuation
					 * indentation */

		parse(hd_type);	/* let parser worry about if, or whatever */
	    }
	    ps.search_brace = btype_2;	/* this should insure that constructs
					 * such as main(){...} and int[]{...}
					 * have their braces put in the right
					 * place */
	    break;

	case unary_op:		/* this could be any unary operation */
	    if (ps.want_blank)
		*e_code++ = ' ';

	    if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) {
		sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
		ps.dumped_decl_indent = 1;
		e_code += strlen(e_code);
	    }
	    else {
		const char *res = token;

		if (ps.in_decl && !ps.block_init) {	/* if this is a unary op
							 * in a declaration, we
							 * should indent this
							 * token */
		    for (i = 0; token[i]; ++i);	/* find length of token */
		    while ((e_code - s_code) < (dec_ind - i)) {
			CHECK_SIZE_CODE;
			*e_code++ = ' ';	/* pad it */
		    }
		}
		if (troff && token[0] == '-' && token[1] == '>')
		    res = "\\(->";
		for (t_ptr = res; *t_ptr; ++t_ptr) {
		    CHECK_SIZE_CODE;
		    *e_code++ = *t_ptr;
		}
	    }
	    ps.want_blank = false;
	    break;

	case binary_op:	/* any binary operation */
	    if (ps.want_blank)
		*e_code++ = ' ';
	    {
		const char *res = token;

		if (troff)
		    switch (token[0]) {
		    case '<':
			if (token[1] == '=')
			    res = "\\(<=";
			break;
		    case '>':
			if (token[1] == '=')
			    res = "\\(>=";
			break;
		    case '!':
			if (token[1] == '=')
			    res = "\\(!=";
			break;
		    case '|':
			if (token[1] == '|')
			    res = "\\(br\\(br";
			else if (token[1] == 0)
			    res = "\\(br";
			break;
		    }
		for (t_ptr = res; *t_ptr; ++t_ptr) {
		    CHECK_SIZE_CODE;
		    *e_code++ = *t_ptr;	/* move the operator */
		}
	    }
	    ps.want_blank = true;
	    break;

	case postop:		/* got a trailing ++ or -- */
	    *e_code++ = token[0];
	    *e_code++ = token[1];
	    ps.want_blank = true;
	    break;

	case question:		/* got a ? */
	    squest++;		/* this will be used when a later colon
				 * appears so we can distinguish the
				 * <c>?<n>:<n> construct */
	    if (ps.want_blank)
		*e_code++ = ' ';
	    *e_code++ = '?';
	    ps.want_blank = true;
	    break;

	case casestmt:		/* got word 'case' or 'default' */
	    scase = true;	/* so we can process the later colon properly */
	    goto copy_id;

	case colon:		/* got a ':' */
	    if (squest > 0) {	/* it is part of the <c>?<n>: <n> construct */
		--squest;
		if (ps.want_blank)
		    *e_code++ = ' ';
		*e_code++ = ':';
		ps.want_blank = true;
		break;
	    }
	    if (ps.in_or_st) {
		*e_code++ = ':';
		ps.want_blank = false;
		break;
	    }
	    ps.in_stmt = false;	/* seeing a label does not imply we are in a
				 * stmt */
	    for (t_ptr = s_code; *t_ptr; ++t_ptr)
		*e_lab++ = *t_ptr;	/* turn everything so far into a label */
	    e_code = s_code;
	    *e_lab++ = ':';
	    *e_lab++ = ' ';
	    *e_lab = '\0';

	    force_nl = ps.pcase = scase;	/* ps.pcase will be used by
						 * dump_line to decide how to
						 * indent the label. force_nl
						 * will force a case n: to be
						 * on a line by itself */
	    scase = false;
	    ps.want_blank = false;
	    break;

	case semicolon:	/* got a ';' */
	    ps.in_or_st = false;/* we are not in an initialization or
				 * structure declaration */
	    scase = false;	/* these will only need resetting in an error */
	    squest = 0;
	    if (ps.last_token == rparen && rparen_count == 0)
		ps.in_parameter_declaration = 0;
	    ps.cast_mask = 0;
	    ps.sizeof_mask = 0;
	    ps.block_init = 0;
	    ps.block_init_level = 0;
	    ps.just_saw_decl--;

	    if (ps.in_decl && s_code == e_code && !ps.block_init)
		while ((e_code - s_code) < (dec_ind - 1)) {
		    CHECK_SIZE_CODE;
		    *e_code++ = ' ';
		}

	    ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first level
						 * structure declaration, we
						 * arent any more */

	    if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {

		/*
		 * This should be true iff there were unbalanced parens in the
		 * stmt.  It is a bit complicated, because the semicolon might
		 * be in a for stmt
		 */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		if (sp_sw) {	/* this is a check for an if, while, etc. with
				 * unbalanced parens */
		    sp_sw = false;
		    parse(hd_type);	/* dont lose the if, or whatever */
		}
	    }
	    *e_code++ = ';';
	    ps.want_blank = true;
	    ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in the
						 * middle of a stmt */

	    if (!sp_sw) {	/* if not if for (;;) */
		parse(semicolon);	/* let parser know about end of stmt */
		force_nl = true;/* force newline after an end of stmt */
	    }
	    break;

	case lbrace:		/* got a '{' */
	    ps.in_stmt = false;	/* dont indent the {} */
	    if (!ps.block_init)
		force_nl = true;/* force other stuff on same line as '{' onto
				 * new line */
	    else if (ps.block_init_level <= 0)
		ps.block_init_level = 1;
	    else
		ps.block_init_level++;

	    if (s_code != e_code && !ps.block_init) {
		if (!btype_2) {
		    dump_line();
		    ps.want_blank = false;
		}
		else if (ps.in_parameter_declaration && !ps.in_or_st) {
		    ps.i_l_follow = 0;
		    if (function_brace_split) {	/* dump the line prior to the
						 * brace ... */
			dump_line();
			ps.want_blank = false;
		    } else	/* add a space between the decl and brace */
			ps.want_blank = true;
		}
	    }
	    if (ps.in_parameter_declaration)
		prefix_blankline_requested = 0;

	    if (ps.p_l_follow > 0) {	/* check for preceding unbalanced
					 * parens */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		if (sp_sw) {	/* check for unclosed if, for, etc. */
		    sp_sw = false;
		    parse(hd_type);
		    ps.ind_level = ps.i_l_follow;
		}
	    }
	    if (s_code == e_code)
		ps.ind_stmt = false;	/* dont put extra indentation on line
					 * with '{' */
	    if (ps.in_decl && ps.in_or_st) {	/* this is either a structure
						 * declaration or an init */
		di_stack[ps.dec_nest++] = dec_ind;
		/* ?		dec_ind = 0; */
	    }
	    else {
		ps.decl_on_line = false;	/* we can't be in the middle of
						 * a declaration, so don't do
						 * special indentation of
						 * comments */
		if (blanklines_after_declarations_at_proctop
			&& ps.in_parameter_declaration)
		    postfix_blankline_requested = 1;
		ps.in_parameter_declaration = 0;
	    }
	    dec_ind = 0;
	    parse(lbrace);	/* let parser know about this */
	    if (ps.want_blank)	/* put a blank before '{' if '{' is not at
				 * start of line */
		*e_code++ = ' ';
	    ps.want_blank = false;
	    *e_code++ = '{';
	    ps.just_saw_decl = 0;
	    break;

	case rbrace:		/* got a '}' */
	    if (ps.p_stack[ps.tos] == decl && !ps.block_init)	/* semicolons can be
								 * omitted in
								 * declarations */
		parse(semicolon);
	    if (ps.p_l_follow) {/* check for unclosed if, for, else. */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		sp_sw = false;
	    }
	    ps.just_saw_decl = 0;
	    ps.block_init_level--;
	    if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
							 * line */
		if (verbose)
		    diag2(0, "Line broken");
		dump_line();
	    }
	    *e_code++ = '}';
	    ps.want_blank = true;
	    ps.in_stmt = ps.ind_stmt = false;
	    if (ps.dec_nest > 0) {	/* we are in multi-level structure
					 * declaration */
		dec_ind = di_stack[--ps.dec_nest];
		if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
		    ps.just_saw_decl = 2;
		ps.in_decl = true;
	    }
	    prefix_blankline_requested = 0;
	    parse(rbrace);	/* let parser know about this */
	    ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
		&& ps.il[ps.tos] >= ps.ind_level;
	    if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
		postfix_blankline_requested = 1;
	    break;

	case swstmt:		/* got keyword "switch" */
	    sp_sw = true;
	    hd_type = swstmt;	/* keep this for when we have seen the
				 * expression */
	    goto copy_id;	/* go move the token into buffer */

	case sp_paren:		/* token is if, while, for */
	    sp_sw = true;	/* the interesting stuff is done after the
				 * expression is scanned */
	    hd_type = (*token == 'i' ? ifstmt :
		       (*token == 'w' ? whilestmt : forstmt));

	    /*
	     * remember the type of header for later use by parser
	     */
	    goto copy_id;	/* copy the token into line */

	case sp_nparen:	/* got else, do */
	    ps.in_stmt = false;
	    if (*token == 'e') {
		if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
		    if (verbose)
			diag2(0, "Line broken");
		    dump_line();/* make sure this starts a line */
		    ps.want_blank = false;
		}
		force_nl = true;/* also, following stuff must go onto new line */
		last_else = 1;
		parse(elselit);
	    }
	    else {
		if (e_code != s_code) {	/* make sure this starts a line */
		    if (verbose)
			diag2(0, "Line broken");
		    dump_line();
		    ps.want_blank = false;
		}
		force_nl = true;/* also, following stuff must go onto new line */
		last_else = 0;
		parse(dolit);
	    }
	    goto copy_id;	/* move the token into line */

	case decl:		/* we have a declaration type (int, register,
				 * etc.) */
	    parse(decl);	/* let parser worry about indentation */
	    if (ps.last_token == rparen && ps.tos <= 1) {
		ps.in_parameter_declaration = 1;
		if (s_code != e_code) {
		    dump_line();
		    ps.want_blank = 0;
		}
	    }
	    if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
		ps.ind_level = ps.i_l_follow = 1;
		ps.ind_stmt = 0;
	    }
	    ps.in_or_st = true;	/* this might be a structure or initialization
				 * declaration */
	    ps.in_decl = ps.decl_on_line = true;
	    if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
		ps.just_saw_decl = 2;
	    prefix_blankline_requested = 0;
	    for (i = 0; token[i++];);	/* get length of token */

	    if (ps.ind_level == 0 || ps.dec_nest > 0) {
		/* global variable or struct member in local variable */
		dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
		tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0);
	    } else {
		/* local variable */
		dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i;
		tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0);
	    }
	    goto copy_id;

	case ident:		/* got an identifier or constant */
	    if (ps.in_decl) {	/* if we are in a declaration, we must indent
				 * identifier */
		if (is_procname == 0 || !procnames_start_line) {
		    if (!ps.block_init) {
			if (troff && !ps.dumped_decl_indent) {
			    if (ps.want_blank)
				*e_code++ = ' ';
			    ps.want_blank = false;
			    sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7);
			    ps.dumped_decl_indent = 1;
			    e_code += strlen(e_code);
			} else {
			    int cur_dec_ind;
			    int pos, startpos;

			    /*
			     * in order to get the tab math right for
			     * indentations that are not multiples of 8 we
			     * need to modify both startpos and dec_ind
			     * (cur_dec_ind) here by eight minus the
			     * remainder of the current starting column
			     * divided by eight. This seems to be a
			     * properly working fix
			     */
			    startpos = e_code - s_code;
			    cur_dec_ind = dec_ind;
			    pos = startpos;
			    if ((ps.ind_level * ps.ind_size) % 8 != 0) {
				pos += (ps.ind_level * ps.ind_size) % 8;
				cur_dec_ind += (ps.ind_level * ps.ind_size) % 8;
			    }

			    if (tabs_to_var) {
				while ((pos & ~7) + 8 <= cur_dec_ind) {
				    CHECK_SIZE_CODE;
				    *e_code++ = '\t';
				    pos = (pos & ~7) + 8;
				}
			    }
			    while (pos < cur_dec_ind) {
				CHECK_SIZE_CODE;
				*e_code++ = ' ';
				pos++;
			    }
			    if (ps.want_blank && e_code - s_code == startpos)
				*e_code++ = ' ';
			    ps.want_blank = false;
			}
		    }
		} else {
		    if (ps.want_blank)
			*e_code++ = ' ';
		    ps.want_blank = false;
		    if (dec_ind && s_code != e_code)
			dump_line();
		    dec_ind = 0;
		}
	    }
	    else if (sp_sw && ps.p_l_follow == 0) {
		sp_sw = false;
		force_nl = true;
		ps.last_u_d = true;
		ps.in_stmt = false;
		parse(hd_type);
	    }
    copy_id:
	    if (ps.want_blank)
		*e_code++ = ' ';
	    if (troff && ps.its_a_keyword) {
		e_code = chfont(&bodyf, &keywordf, e_code);
		for (t_ptr = token; *t_ptr; ++t_ptr) {
		    CHECK_SIZE_CODE;
		    *e_code++ = keywordf.allcaps && islower(*t_ptr)
			? toupper(*t_ptr) : *t_ptr;
		}
		e_code = chfont(&keywordf, &bodyf, e_code);
	    }
	    else
		for (t_ptr = token; *t_ptr; ++t_ptr) {
		    CHECK_SIZE_CODE;
		    *e_code++ = *t_ptr;
		}
	    ps.want_blank = true;
	    break;

	case period:		/* treat a period kind of like a binary
				 * operation */
	    *e_code++ = '.';	/* move the period into line */
	    ps.want_blank = false;	/* dont put a blank after a period */
	    break;

	case comma:
	    ps.want_blank = (s_code != e_code);	/* only put blank after comma
						 * if comma does not start the
						 * line */
	    if (ps.in_decl && is_procname == 0 && !ps.block_init)
		while ((e_code - s_code) < (dec_ind - 1)) {
		    CHECK_SIZE_CODE;
		    *e_code++ = ' ';
		}

	    *e_code++ = ',';
	    if (ps.p_l_follow == 0) {
		if (ps.block_init_level <= 0)
		    ps.block_init = 0;
		if (break_comma && (!ps.leave_comma || compute_code_target() + (e_code - s_code) > max_col - 8))
		    force_nl = true;
	    }
	    break;

	case preesc:		/* got the character '#' */
	    if ((s_com != e_com) ||
		    (s_lab != e_lab) ||
		    (s_code != e_code))
		dump_line();
	    *e_lab++ = '#';	/* move whole line to 'label' buffer */
	    {
		int         in_comment = 0;
		int         com_start = 0;
		char        quote = 0;
		int         com_end = 0;

		while (*buf_ptr == ' ' || *buf_ptr == '\t') {
		    buf_ptr++;
		    if (buf_ptr >= buf_end)
			fill_buffer();
		}
		while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
		    CHECK_SIZE_LAB;
		    *e_lab = *buf_ptr++;
		    if (buf_ptr >= buf_end)
			fill_buffer();
		    switch (*e_lab++) {
		    case BACKSLASH:
			if (troff)
			    *e_lab++ = BACKSLASH;
			if (!in_comment) {
			    *e_lab++ = *buf_ptr++;
			    if (buf_ptr >= buf_end)
				fill_buffer();
			}
			break;
		    case '/':
			if (*buf_ptr == '*' && !in_comment && !quote) {
			    in_comment = 1;
			    *e_lab++ = *buf_ptr++;
			    com_start = e_lab - s_lab - 2;
			}
			break;
		    case '"':
			if (quote == '"')
			    quote = 0;
			break;
		    case '\'':
			if (quote == '\'')
			    quote = 0;
			break;
		    case '*':
			if (*buf_ptr == '/' && in_comment) {
			    in_comment = 0;
			    *e_lab++ = *buf_ptr++;
			    com_end = e_lab - s_lab;
			}
			break;
		    }
		}

		while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
		    e_lab--;
		if (e_lab - s_lab == com_end && bp_save == 0) {	/* comment on
								 * preprocessor line */
		    if (sc_end == 0)	/* if this is the first comment, we
					 * must set up the buffer */
			sc_end = &(save_com[0]);
		    else {
			*sc_end++ = '\n';	/* add newline between
						 * comments */
			*sc_end++ = ' ';
			--line_no;
		    }
		    bcopy(s_lab + com_start, sc_end, com_end - com_start);
		    sc_end += com_end - com_start;
		    if (sc_end >= &save_com[sc_size])
			abort();
		    e_lab = s_lab + com_start;
		    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
			e_lab--;
		    bp_save = buf_ptr;	/* save current input buffer */
		    be_save = buf_end;
		    buf_ptr = save_com;	/* fix so that subsequent calls to
					 * lexi will take tokens out of
					 * save_com */
		    *sc_end++ = ' ';	/* add trailing blank, just in case */
		    buf_end = sc_end;
		    sc_end = 0;
		}
		*e_lab = '\0';	/* null terminate line */
		ps.pcase = false;
	    }

	    if (strncmp(s_lab, "#if", 3) == 0) {
		if (blanklines_around_conditional_compilation) {
		    int c;
		    prefix_blankline_requested++;
		    while ((c = getc(input)) == '\n');
		    ungetc(c, input);
		}
		if ((size_t)ifdef_level < sizeof(state_stack)/sizeof(state_stack[0])) {
		    match_state[ifdef_level].tos = -1;
		    state_stack[ifdef_level++] = ps;
		}
		else
		    diag2(1, "#if stack overflow");
	    }
	    else if (strncmp(s_lab, "#else", 5) == 0)
		if (ifdef_level <= 0)
		    diag2(1, "Unmatched #else");
		else {
		    match_state[ifdef_level - 1] = ps;
		    ps = state_stack[ifdef_level - 1];
		}
	    else if (strncmp(s_lab, "#endif", 6) == 0) {
		if (ifdef_level <= 0)
		    diag2(1, "Unmatched #endif");
		else {
		    ifdef_level--;

#ifdef undef
		    /*
		     * This match needs to be more intelligent before the
		     * message is useful
		     */
		    if (match_state[ifdef_level].tos >= 0
			  && bcmp(&ps, &match_state[ifdef_level], sizeof ps))
			diag2(0, "Syntactically inconsistent #ifdef alternatives");
#endif
		}
		if (blanklines_around_conditional_compilation) {
		    postfix_blankline_requested++;
		    n_real_blanklines = 0;
		}
	    }
	    break;		/* subsequent processing of the newline
				 * character will cause the line to be printed */

	case comment:		/* we have gotten a / followed by * this is a biggie */
	    if (flushed_nl) {	/* we should force a broken line here */
		flushed_nl = false;
		dump_line();
		ps.want_blank = false;	/* dont insert blank at line start */
		force_nl = false;
	    }
	    pr_comment();
	    break;
	}			/* end of big switch stmt */

	*e_code = '\0';		/* make sure code section is null terminated */
	if (type_code != comment && type_code != newline && type_code != preesc)
	    ps.last_token = type_code;
    }				/* end of main while (1) loop */
}
Beispiel #6
0
//***********************************************************************
// $TEXT(entryref)
//
// the entire string "entryref" is passed in one variable, eval it here
//
short Dtext(u_char *ret_buffer, cstring *str)	// $TEXT()
{ int i = 0;					// a handy int
  int j = 0;					// and another
  u_char slen;					// saved length
  short s;					// for functions
  int off = 1;					// line offset
  u_char rou[4+MAX_NAME_BYTES];			// routine name
  u_char tag[4+MAX_NAME_BYTES];			// the tag
  cstring *cr;					// the rou
  cstring *ct;					// and the tag

  ret_buffer[0] = '\0';				// JIC
  ct = (cstring *) &tag[0];			// use it this way
  cr = (cstring *) &rou[0];			// ditto  
  ct->len = 0;					// assume no tag
  cr->len = 0;					// no routine for now

  if (bcmp("+0\0", str->buf, 3) == 0)		// $T(+0) ?
  { for (i = 0; i < MAX_NAME_BYTES; i++)		// copy rou name
    { if (!partab.jobtab->dostk[partab.jobtab->cur_do].rounam.var_cu[i])
        break;					// quit when done
      ret_buffer[i] = 
        partab.jobtab->dostk[partab.jobtab->cur_do].rounam.var_cu[i]; // copy
    }
    ret_buffer[i] = '\0';			// null terminate
    return (short) i;				// and exit
  }
  if ((str->buf[i] != '+') && (str->buf[i] != '^')) // is there a tag
  { while (j < MAX_NAME_BYTES)
    { if ((i == 0) && (str->buf[i] == '%'))	// leading %
      { ct->buf[j++] = str->buf[i++];		// copy it
        continue;				// and go for more
      }
      if (isalnum(str->buf[i]) == 0) break;	// done
      ct->buf[j++] = str->buf[i++];		// copy it
    }
    ct->buf[j] = '\0';				// null terminate tag
    ct->len = j;				// save the length
    off = 0;					// change offset to zero
    while ((str->buf[i] != '+') &&
	   (str->buf[i] != '^') &&
	   (str->buf[i] != '\0')) i++;		// skip to + ^ or null
  }						// end tag processing
  if (str->buf[i] == '+')			// if we have a plus
  { off = 0;					// clear offset
    i++;					// skip the +
    while (isdigit(str->buf[i]) != 0)		// for all digits
      off = (off * 10) + (str->buf[i++] - '0');	// extract the offset
  }						// end offset stuf
  if ((str->buf[i] != '^') && (str->buf[i] != '\0'))
    return -(ERRMLAST + ERRZ12);		// complain
  j = 0;					// clear rou ptr
  if (str->buf[i] == '^')			// routine name
  { i++;					// skip the ^
    while (j < MAX_NAME_BYTES)
    { if ((j == 0) && (str->buf[i] == '%'))	// leading %
      { cr->buf[j++] = str->buf[i++];		// copy it
        continue;				// and go for more
      }
      if (isalnum(str->buf[i]) == 0) break;	// done
      cr->buf[j++] = str->buf[i++];		// copy it
    }
    cr->buf[j] = '\0';				// null terminate rou
    cr->len = j;				// save the length
  }
  else						// we need the current routine
  { for (j = 0; j < MAX_NAME_BYTES; j++)
      if ((cr->buf[j] = 
            partab.jobtab->dostk[partab.jobtab->cur_do].rounam.var_cu[j])
		== '\0') break;			// copy till done
    cr->buf[j] = '\0';				// null terminate rou
    cr->len = j;				// save the length
  }
  if (cr->len == 0) return 0;			// no routine supplied -> null
  if ((ct->len == 0) && (!off))			// just the name reqd?
    return mcopy(cr->buf, ret_buffer, cr->len);	// return the name
  X_set("$ROUTINE", &partab.src_var.name.var_cu[0], 8); // setup for DB_Get
  partab.src_var.volset = partab.jobtab->rvol;	// vol
  partab.src_var.uci = partab.jobtab->ruci;	// uci
  if (cr->buf[0] == '%')			// manager routine?
    partab.src_var.uci = 1;			// point there
  partab.src_var.slen = 0;			// init key size
  s = UTIL_Key_Build(cr, &partab.src_var.key[0]); // first key
  if (s < 0) return s;				// die on error
  slen = s;					// save key size
  if (ct->len == 0)				// no tag?
  { ct->len = itocstring(ct->buf, off);		// cstring off
    s = UTIL_Key_Build(ct,
		       &partab.src_var.key[slen]); // next key
    if (s < 0) return s;			// die on error
    partab.src_var.slen = s + slen;		// save key size
    s = DB_Get(&partab.src_var, ret_buffer);	// get it
    if (s < 0)
    { ret_buffer[0] = '\0';			// nothing
      s = 0;					// zero length
    }
    return s;					// and return it
  }
  for (j = 1; ; j++)				// need to read all lines
  { cr->len = itocstring(cr->buf, j);		// cstring j
    s = UTIL_Key_Build(cr,
		       &partab.src_var.key[slen]); // next key
    if (s < 0) return s;			// die on error
    partab.src_var.slen = s + slen;		// save key size
    s = DB_Get(&partab.src_var, ret_buffer);	// get it
    if (s < 0)
    { ret_buffer[0] = '\0';			// nothing
      return 0;					// zero length
    }
    for (i = 0; i < ct->len; i++)		// check the tag
      if (ret_buffer[i] != ct->buf[i]) break;	// quit if different
    if (i < ct->len) continue;			// go for next if no match
    if ((ret_buffer[i] != ' ') &&		// must be space
        (ret_buffer[i] != '(') &&		//	or (
	(ret_buffer[i] != '\0')) continue;	//	or null
    if (off == 0) return s;			// no offset - all done
    j = j + off;				// add the offset
    cr->len = itocstring(cr->buf, j);		// cstring j
    s = UTIL_Key_Build(cr,
		       &partab.src_var.key[slen]); // next key
    if (s < 0) return s;			// die on error
    partab.src_var.slen = s + slen;		// save key size
    s = DB_Get(&partab.src_var, ret_buffer);	// get it
    if (s < 0)
    { ret_buffer[0] = '\0';			// nothing
      s = 0;					// zero length
    }
    return s;					// done
  }
}
Beispiel #7
0
/*
 * Probe and vendor-specific initialization routine for NE1000/2000 boards
 */
int
ed_probe_Novell_generic(device_t dev, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	u_int   memsize;
	int	error;
	u_char  tmp;
	static char test_pattern[32] = "THIS is A memory TEST pattern";
	char    test_buffer[32];

	/* Reset the board */
	if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
		ed_asic_outb(sc, ED_NOVELL_RESET, 0);
		DELAY(200);
	}
	tmp = ed_asic_inb(sc, ED_NOVELL_RESET);

	/*
	 * I don't know if this is necessary; probably cruft leftover from
	 * Clarkson packet driver code. Doesn't do a thing on the boards I've
	 * tested. -DG
	 */
	ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
	DELAY(5000);

	/*
	 * This is needed because some NE clones apparently don't reset the
	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
	 * - this makes the probe invasive! ...Done against my better
	 * judgement. -DLG
	 */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
	DELAY(5000);

	/* Make sure that we really have an 8390 based board */
	if (!ed_probe_generic8390(sc))
		return (ENXIO);

	sc->vendor = ED_VENDOR_NOVELL;
	sc->mem_shared = 0;
	sc->cr_proto = ED_CR_RD2;

	/*
	 * Test the ability to read and write to the NIC memory. This has the
	 * side affect of determining if this is an NE1000 or an NE2000.
	 */

	/*
	 * This prevents packets from being stored in the NIC memory when the
	 * readmem routine turns on the start bit in the CR.
	 */
	ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);

	/* Temporarily initialize DCR for byte operations */
	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);

	ed_nic_outb(sc, ED_P0_PSTART, 8192 / ED_PAGE_SIZE);
	ed_nic_outb(sc, ED_P0_PSTOP, 16384 / ED_PAGE_SIZE);

	/*
	 * Some devices identify themselves.  Some of those devices
	 * can't handle being probed, so we allow forcing a mode.  If
	 * these flags are set, force it, otherwise probe.
	 */
	if (flags & ED_FLAGS_FORCE_8BIT_MODE) {
		sc->isa16bit = 0;
		sc->type = ED_TYPE_NE1000;
		sc->type_str = "NE1000";
	} else if (flags & ED_FLAGS_FORCE_16BIT_MODE) {
		sc->isa16bit = 1;
		sc->type = ED_TYPE_NE2000;
		sc->type_str = "NE2000";
		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
		ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
		ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
	} else {
		/*
		 * Write a test pattern in byte mode. If this fails, then there
		 * probably isn't any memory at 8k - which likely means that the board
		 * is an NE2000.
		 */
		ed_pio_writemem(sc, test_pattern, 8192, sizeof(test_pattern));
		ed_pio_readmem(sc, 8192, test_buffer, sizeof(test_pattern));

		if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
			sc->type = ED_TYPE_NE1000;
			sc->type_str = "NE1000";
			sc->isa16bit = 0;
		} else {
			/* Not an NE1000 - try NE2000 */
			sc->isa16bit = 1;
			ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
			ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE);
			ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE);
			/*
			 * Write a test pattern in word mode. If this also fails, then
			 * we don't know what this board is.
			 */
			ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
			ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
			if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
				sc->type = ED_TYPE_NE2000;
				sc->type_str = "NE2000";
			} else {
				return (ENXIO);
			}
		}
	}
	sc->chip_type = ED_CHIP_TYPE_DP8390;

	/* 8k of memory plus an additional 8k if 16bit */
	memsize = 8192 + sc->isa16bit * 8192;
	sc->mem_size = memsize;

	/* NIC memory doesn't start at zero on an NE board */
	/* The start address is tied to the bus width */
	sc->mem_start = 8192 + sc->isa16bit * 8192;
	sc->mem_end = sc->mem_start + memsize;
	sc->tx_page_start = memsize / ED_PAGE_SIZE;

	if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) {
		error = ed_probe_gwether(dev);
		if (error)
			return (error);
	}

	/*
	 * Use one xmit buffer if < 16k, two buffers otherwise (if not told
	 * otherwise).
	 */
	if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
		sc->txb_cnt = 1;
	else
		sc->txb_cnt = 2;

	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
	sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;

	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
	/* clear any pending interrupts that might have occurred above */
	ed_nic_outb(sc, ED_P0_ISR, 0xff);

	sc->sc_write_mbufs = ed_pio_write_mbufs;
	return (0);
}
/* Function: GetSegmentBitmap
 *
 * Description: Return bitmap segment corresponding to given startBit.
 * 
 *	1. Calculate the segment number for given bit.
 *	2. If the segment exists in full segment list,
 *			If bitOperation is to clear bits, 
 *			a. Remove segment from full segment list.
 *			b. Insert a full segment in the bitmap tree.
 *			Else return pointer to dummy full segment
 *	3. If segment found in tree, it is partially full.  Return it.
 *	4. If (2) and (3) are not true, it is a empty segment.
 *			If bitOperation is to set bits,
 *			a. Insert empty segment in the bitmap tree.
 *			Else return pointer to dummy empty segment.
 *
 * Input:	
 *	1. startBit - bit number (block number) to lookup
 *	2. buffer - pointer to return pointer to bitmap segment
 *	3. bitOperation - intent for new segment
 *		kSettingBits	- caller wants to set bits
 *		kClearingBits	- caller wants to clear bits
 *		kTestingBits	- caller wants to test bits.
 *
 * Output:
 *	1. buffer - pointer to desired segment 
 *	returns zero on success, -1 on failure.
 */
static int GetSegmentBitmap(UInt32 startBit, UInt32 **buffer, int bitOperation)
{
	UInt32 segment;
	BMS_Node *segNode = NULL;
	
	*buffer = NULL;
	segment = startBit / kBitsPerSegment;

	// for a full seqment...
	if (bit_test(gFullSegmentList, segment)) {
		if (bitOperation == kClearingBits) {
                    bit_clear(gFullSegmentList, segment);
					--gFullSegments;
                    if ((segNode = BMS_Insert(segment, kFullSegment)) != NULL)
                        *buffer = &segNode->bitmap[0];
		} else
			*buffer = gFullBitmapSegment;
	
	// for a  partially full segment..
	} else if ((segNode = BMS_Lookup(segment)) != NULL) {
			*buffer = &segNode->bitmap[0];
	
	// for an empty segment...
	} else {
		if (bitOperation == kSettingBits) { 
			if ((segNode = BMS_Insert(segment, kEmptySegment)) != NULL)
				*buffer = &segNode->bitmap[0];
		} else	
			*buffer = gEmptyBitmapSegment;
	}
		
	if (*buffer == NULL) {
#if _VBC_DEBUG_
		plog("GetSegmentBitmap: couldn't get a node for block %d, segment %d\n", startBit, segment);
#endif
		return (-1); /* oops */
	}

#if 0
	if (segNode) {
		int i;
		plog("  segment %d: L=0x%08x, R=0x%08x \n< ",
			(int)segNode->segment, (int)segNode->left, segNode->right);
		for (i = 0; i < kWordsPerSegment; ++i) {
			plog("0x%08x ", segNode->bitmap[i]);
			if ((i & 0x3) == 0x3)
				plog("\n  ");
		}
		plog("\n");
	}

	if (bitOperation == kSettingBits && *buffer && bcmp(*buffer, gFullBitmapSegment, kBytesPerSegment) == 0) {
		plog("*** segment %d (start blk %d) is already full!\n", segment, startBit);
		exit(5);
	}
	if (bitOperation == kClearingBits && *buffer && bcmp(*buffer, gEmptyBitmapSegment, kBytesPerSegment) == 0) {
		plog("*** segment %d (start blk %d) is already empty!\n", segment, startBit);
		exit(5);
	}
#endif

	return (0);
}
Beispiel #9
0
/*
 * 
 * Called from ip_output().
 * 1 = drop packet, 0 = continue processing packet,
 * -1 = packet was reinjected and stop processing packet
 */
int
ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error)
{
#ifdef IPSEC
	struct secpolicy *sp = NULL;
	struct tdb_ident *tdbi;
	struct m_tag *mtag;
	/*
	 * Check the security policy (SP) for the packet and, if
	 * required, do IPsec-related processing.  There are two
	 * cases here; the first time a packet is sent through
	 * it will be untagged and handled by ipsec4_checkpolicy.
	 * If the packet is resubmitted to ip_output (e.g. after
	 * AH, ESP, etc. processing), there will be a tag to bypass
	 * the lookup and related policy checking.
	 */
	mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
	if (mtag != NULL) {
		tdbi = (struct tdb_ident *)(mtag + 1);
		sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
		if (sp == NULL)
			*error = -EINVAL;	/* force silent drop */
		m_tag_delete(*m, mtag);
	} else {
		sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
					error, inp);
	}
	/*
	 * There are four return cases:
	 *    sp != NULL	 	    apply IPsec policy
	 *    sp == NULL, error == 0	    no IPsec handling needed
	 *    sp == NULL, error == -EINVAL  discard packet w/o error
	 *    sp == NULL, error != 0	    discard packet, report error
	 */
	if (sp != NULL) {
		/* Loop detection, check if ipsec processing already done */
		KASSERT(sp->req != NULL, ("ip_output: no ipsec request"));
		for (mtag = m_tag_first(*m); mtag != NULL;
		     mtag = m_tag_next(*m, mtag)) {
			if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
				continue;
			if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
			    mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
				continue;
			/*
			 * Check if policy has an SA associated with it.
			 * This can happen when an SP has yet to acquire
			 * an SA; e.g. on first reference.  If it occurs,
			 * then we let ipsec4_process_packet do its thing.
			 */
			if (sp->req->sav == NULL)
				break;
			tdbi = (struct tdb_ident *)(mtag + 1);
			if (tdbi->spi == sp->req->sav->spi &&
			    tdbi->proto == sp->req->sav->sah->saidx.proto &&
			    bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst,
				 sizeof (union sockaddr_union)) == 0) {
				/*
				 * No IPsec processing is needed, free
				 * reference to SP.
				 *
				 * NB: null pointer to avoid free at
				 *     done: below.
				 */
				KEY_FREESP(&sp), sp = NULL;
				goto done;
			}
		}

		/*
		 * Do delayed checksums now because we send before
		 * this is done in the normal processing path.
		 */
		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
			in_delayed_cksum(*m);
			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
		}
#ifdef SCTP
		if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
			struct ip *ip = mtod(*m, struct ip *);

			sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2));
			(*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
		}
#endif

		/* NB: callee frees mbuf */
		*error = ipsec4_process_packet(*m, sp->req, *flags, 0);
		if (*error == EJUSTRETURN) {
			/*
			 * We had a SP with a level of 'use' and no SA. We
			 * will just continue to process the packet without
			 * IPsec processing and return without error.
			 */
			*error = 0;
			goto done;
		}
		/*
		 * Preserve KAME behaviour: ENOENT can be returned
		 * when an SA acquire is in progress.  Don't propagate
		 * this to user-level; it confuses applications.
		 *
		 * XXX this will go away when the SADB is redone.
		 */
		if (*error == ENOENT)
			*error = 0;
		goto reinjected;
	} else {	/* sp == NULL */
static int
ether_add_proto_internal(
	struct ifnet					*ifp,
	protocol_family_t				protocol,
	const struct ifnet_demux_desc	*demux)
{
	struct en_desc *ed;
	struct ether_desc_blk_str *desc_blk = (struct ether_desc_blk_str *)ifp->family_cookie;
	u_int32_t i;
	
	switch (demux->type) {
		/* These types are supported */
		/* Top three are preferred */
		case DLIL_DESC_ETYPE2:
			if (demux->datalen != 2) {
				return EINVAL;
			}
			break;
		
		case DLIL_DESC_SAP:
			if (demux->datalen != 3) {
				return EINVAL;
			}
			break;
		
		case DLIL_DESC_SNAP:
			if (demux->datalen != 5) {
				return EINVAL;
			}
			break;
			
		default:
			return ENOTSUP;
	}
	
	// Verify a matching descriptor does not exist.
	if (desc_blk != NULL) {
		switch (demux->type) {
			case DLIL_DESC_ETYPE2:
				for (i = 0; i < desc_blk->n_max_used; i++) {
					if (desc_blk->block_ptr[i].type == DLIL_DESC_ETYPE2 &&
						desc_blk->block_ptr[i].data[0] ==
						*(u_int16_t*)demux->data) {
						return EADDRINUSE;
					}
				}
				break;
			case DLIL_DESC_SAP:
			case DLIL_DESC_SNAP:
				for (i = 0; i < desc_blk->n_max_used; i++) {
					if (desc_blk->block_ptr[i].type == demux->type &&
						bcmp(desc_blk->block_ptr[i].data, demux->data,
							 demux->datalen) == 0) {
						return EADDRINUSE;
					}
				}
				break;
		}
	}
	
	// Check for case where all of the descriptor blocks are in use
	if (desc_blk == NULL || desc_blk->n_used == desc_blk->n_count) {
		struct ether_desc_blk_str *tmp;
		u_long	new_count = ETHER_DESC_BLK_SIZE;
		u_long	new_size;
		u_long	old_size = 0;
		
		i = 0;
		
		if (desc_blk) {
			new_count += desc_blk->n_count;
			old_size = desc_blk->n_count * sizeof(struct en_desc) + ETHER_DESC_HEADER_SIZE;
			i = desc_blk->n_used;
		}
		
		new_size = new_count * sizeof(struct en_desc) + ETHER_DESC_HEADER_SIZE;
		
		tmp = _MALLOC(new_size, M_IFADDR, M_WAITOK);
		if (tmp  == 0) {
			/*
			 * Remove any previous descriptors set in the call.
			 */
			return ENOMEM;
		}

		bzero(((char *)tmp) + old_size, new_size - old_size);
		if (desc_blk) {
			bcopy(desc_blk, tmp, old_size);
			FREE(desc_blk, M_IFADDR);
		}
		desc_blk = tmp;
		ifp->family_cookie = (u_long)desc_blk;
		desc_blk->n_count = new_count;
	}
	else {
		/* Find a free entry */
		for (i = 0; i < desc_blk->n_count; i++) {
			if (desc_blk->block_ptr[i].type == 0) {
				break;
			}
		}
	}
	
	/* Bump n_max_used if appropriate */
	if (i + 1 > desc_blk->n_max_used) {
		desc_blk->n_max_used = i + 1;
	}
	
	ed = &desc_blk->block_ptr[i];
	ed->protocol_family = protocol;
	ed->data[0] = 0;
	ed->data[1] = 0;
	
	switch (demux->type) {
		case DLIL_DESC_ETYPE2:
			/* 2 byte ethernet raw protocol type is at native_type */
			/* prtocol must be in network byte order */
			ed->type = DLIL_DESC_ETYPE2;
			ed->data[0] = *(u_int16_t*)demux->data;
			break;
		
		case DLIL_DESC_SAP:
			ed->type = DLIL_DESC_SAP;
			bcopy(demux->data, &ed->data[0], 3);
			break;
		
		case DLIL_DESC_SNAP: {
			u_int8_t*	pDest = ((u_int8_t*)&ed->data[0]) + 3;
			ed->type = DLIL_DESC_SNAP;
			bcopy(demux->data, pDest, 5);
			}
			break;
	}
	
	desc_blk->n_used++;
	
	return 0;
}
/*
 * The function is called after we read and decrypt data.
 *
 * g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> G_ELI_AUTH_READ_DONE -> g_io_deliver
 */
static int
g_eli_auth_read_done(struct cryptop *crp)
{
	struct g_eli_softc *sc;
	struct bio *bp;

	if (crp->crp_etype == EAGAIN) {
		if (g_eli_crypto_rerun(crp) == 0)
			return (0);
	}
	bp = (struct bio *)crp->crp_opaque;
	bp->bio_inbed++;
	if (crp->crp_etype == 0) {
		bp->bio_completed += crp->crp_olen;
		G_ELI_DEBUG(3, "Crypto READ request done (%d/%d) (add=%jd completed=%jd).",
		    bp->bio_inbed, bp->bio_children, (intmax_t)crp->crp_olen, (intmax_t)bp->bio_completed);
	} else {
		G_ELI_DEBUG(1, "Crypto READ request failed (%d/%d) error=%d.",
		    bp->bio_inbed, bp->bio_children, crp->crp_etype);
		if (bp->bio_error == 0)
			bp->bio_error = crp->crp_etype;
	}
	sc = bp->bio_to->geom->softc;
	g_eli_key_drop(sc, crp->crp_desc->crd_next->crd_key);
	/*
	 * Do we have all sectors already?
	 */
	if (bp->bio_inbed < bp->bio_children)
		return (0);
	if (bp->bio_error == 0) {
		u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
		u_char *srcdata, *dstdata, *auth;
		off_t coroff, corsize;

		/*
		 * Verify data integrity based on calculated and read HMACs.
		 */
		/* Sectorsize of decrypted provider eg. 4096. */
		decr_secsize = bp->bio_to->sectorsize;
		/* The real sectorsize of encrypted provider, eg. 512. */
		encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
		/* Number of data bytes in one encrypted sector, eg. 480. */
		data_secsize = sc->sc_data_per_sector;
		/* Number of sectors from decrypted provider, eg. 2. */
		nsec = bp->bio_length / decr_secsize;
		/* Number of sectors from encrypted provider, eg. 18. */
		nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
		/* Last sector number in every big sector, eg. 9. */
		lsec = sc->sc_bytes_per_sector / encr_secsize;

		srcdata = bp->bio_driver2;
		dstdata = bp->bio_data;
		auth = srcdata + encr_secsize * nsec;
		coroff = -1;
		corsize = 0;

		for (i = 1; i <= nsec; i++) {
			data_secsize = sc->sc_data_per_sector;
			if ((i % lsec) == 0)
				data_secsize = decr_secsize % data_secsize;
			if (bcmp(srcdata, auth, sc->sc_alen) != 0) {
				/*
				 * Curruption detected, remember the offset if
				 * this is the first corrupted sector and
				 * increase size.
				 */
				if (bp->bio_error == 0)
					bp->bio_error = -1;
				if (coroff == -1) {
					coroff = bp->bio_offset +
					    (dstdata - (u_char *)bp->bio_data);
				}
				corsize += data_secsize;
			} else {
				/*
				 * No curruption, good.
				 * Report previous corruption if there was one.
				 */
				if (coroff != -1) {
					G_ELI_DEBUG(0, "%s: Failed to authenticate %jd "
					    "bytes of data at offset %jd.",
					    sc->sc_name, (intmax_t)corsize,
					    (intmax_t)coroff);
					coroff = -1;
					corsize = 0;
				}
				bcopy(srcdata + sc->sc_alen, dstdata,
				    data_secsize);
			}
			srcdata += encr_secsize;
			dstdata += data_secsize;
			auth += sc->sc_alen;
		}
		/* Report previous corruption if there was one. */
		if (coroff != -1) {
			G_ELI_DEBUG(0, "%s: Failed to authenticate %jd "
			    "bytes of data at offset %jd.",
			    sc->sc_name, (intmax_t)corsize, (intmax_t)coroff);
		}
	}
	free(bp->bio_driver2, M_ELI);
	bp->bio_driver2 = NULL;
	if (bp->bio_error != 0) {
		if (bp->bio_error == -1)
			bp->bio_error = EINVAL;
		else {
			G_ELI_LOGREQ(0, bp,
			    "Crypto READ request failed (error=%d).",
			    bp->bio_error);
		}
		bp->bio_completed = 0;
	}
	/*
	 * Read is finished, send it up.
	 */
	g_io_deliver(bp, bp->bio_error);
	atomic_subtract_int(&sc->sc_inflight, 1);
	return (0);
}
Beispiel #12
0
void
udp_relay(int cs, int ss, struct sockaddr_storage *udp)
{
    fd_set sockfd, ctlfd;
    struct sockaddr_storage sender;
    struct timeval timeout;

    uint8_t buf[65535];    // BIG!!
    uint8_t outbuf[65535]; // BIG!!
    ssize_t recvlen = 0;
    socklen_t addrlen = 0;
    struct socks_udpmsg *udpmsg = NULL;

    int is_clientmsg = 0;
    int learn_client = 0;

#ifdef IPHONE_OS
    pthread_mutex_lock(&stat_lock);
    stat_connections++;
    pthread_mutex_unlock(&stat_lock);
#endif

    sender.ss_family = udp->ss_family;
    if (udp->ss_family == AF_INET6)
      {
	struct sockaddr_in6 *udp_ip6 = NULL;
	udp_ip6 = (struct sockaddr_in6*)udp;

	if (udp_ip6->sin6_port == 0)
	    learn_client = 1;
      }
    else
      {
	struct sockaddr_in *udp_ip4 = NULL;
	udp_ip4 = (struct sockaddr_in*)udp;

	if (udp_ip4->sin_port == 0)
	    learn_client = 1;
      }

    errno = 0;

    for (;;)
      {
	FD_ZERO(&ctlfd);
	FD_SET(cs, &ctlfd);

	timeout.tv_sec  = 0;
	timeout.tv_usec = 100;

	if (select(cs + 1, &ctlfd, NULL, NULL, &timeout) == 1)
	  {
	    char c;
	    if (recv(cs, &c, 1, MSG_PEEK | MSG_DONTWAIT) == 0)
	      {
		msg_out(norm, "UDP: control channel closed\n");
		break;
	      }
	  }

	FD_ZERO(&sockfd);
	FD_SET(ss, &sockfd);

	timeout.tv_sec  = 0;
	timeout.tv_usec = 100;

	if (select(ss + 1, &sockfd, NULL, NULL, &timeout) == 0)
	    continue;

	bzero(buf, sizeof(buf));
	bzero(&sender, sizeof(struct sockaddr_storage));
	if (sender.ss_family == AF_INET6)
	  addrlen = sizeof(struct sockaddr_in6);
	else
	  addrlen = sizeof(struct sockaddr_in);

	recvlen = recvfrom(ss, buf, sizeof(buf), 0,
			   (struct sockaddr*)&sender, &addrlen);
	if (recvlen <= 0)
	  {
	    msg_out(warn, "UDP: recvfrom() - %s\n", strerror(errno));
	    break;
	  }

	/* validate request - who sent it? */
	udpmsg = (struct socks_udpmsg*)buf;
	is_clientmsg = 0;
	if (udpmsg->rsv == 0)
	  {
	    switch (udpmsg->atyp)
	      {
	      case S5ATIPV4:
		  {
		    struct sockaddr_in *udp_ip4 = (struct sockaddr_in*)udp;
		    struct sockaddr_in *sender_ip4 = (struct sockaddr_in*)&sender;

		    if (bcmp(&sender_ip4->sin_addr.s_addr,
			     &udp_ip4->sin_addr.s_addr,
			     sizeof(udp_ip4->sin_addr)) == 0)
		      is_clientmsg = 1;
		  }
		break;
		
	      case S5ATIPV6:
		  {
		    struct sockaddr_in6 *udp_ip6 = (struct sockaddr_in6*)udp;
		    struct sockaddr_in6 *sender_ip6 = (struct sockaddr_in6*)&sender;

//		    if (sender_ip6->sin6_port == udp_ip6->sin6_port)
		    if (bcmp(sender_ip6->sin6_addr.s6_addr,
			     udp_ip6->sin6_addr.s6_addr,
			     sizeof(udp_ip6->sin6_addr.s6_addr)) == 0)
		      is_clientmsg = 1;
		  }
		break;

	      default:
		break;
	      }
	  }

	if (is_clientmsg == 1)
	  {
	    /* looks like our client sent it */
	    if (udpmsg->atyp == S5ATIPV4)
	      {
		struct sockaddr_in remote;
		bzero(&remote, sizeof(remote));

		remote.sin_addr.s_addr = udpmsg->_addr._ip4.addr;
		remote.sin_port        = udpmsg->_addr._ip4.port;
		remote.sin_family      = AF_INET;
		remote.sin_len         = sizeof(remote);
		addrlen = sizeof(remote);

		if (learn_client == 1)
		  {
		    msg_out(norm, "UDP: client is sending on port %d\n",
			    ntohs(((struct sockaddr_in*)&sender)->sin_port));
		    ((struct sockaddr_in*)udp)->sin_port = ((struct sockaddr_in*)&sender)->sin_port;

		    learn_client = 0;
		  }

		if (sendto(ss, &buf[SOCKS_UDPMSG_V4_SIZE(udpmsg)],
			   recvlen - SOCKS_UDPMSG_V4_SIZE(udpmsg), 0,
			   (struct sockaddr*)&remote, addrlen) < 0)
		  {
		    msg_out(crit, "UDP: error sending IPv4 request to server\n");
		    break;
		  }
	      }
	    else
	      {
		struct sockaddr_in6 remote;
		bzero(&remote, sizeof(remote));

		remote.sin6_addr   = udpmsg->_addr._ip6.addr;
		remote.sin6_port   = udpmsg->_addr._ip6.port;
		remote.sin6_family = AF_INET6;
		remote.sin6_len    = sizeof(remote);
		addrlen = sizeof(remote);

		if (learn_client == 1)
		  {
		    msg_out(norm, "UDP: client is sending on port %d\n",
			    ntohs(((struct sockaddr_in6*)&sender)->sin6_port));
		    ((struct sockaddr_in6*)udp)->sin6_port = ((struct sockaddr_in6*)&sender)->sin6_port;

		    learn_client = 0;
		  }
		if (sendto(ss, &buf[SOCKS_UDPMSG_V6_SIZE(udpmsg)],
			   recvlen - SOCKS_UDPMSG_V6_SIZE(udpmsg), 0,
			   (struct sockaddr*)&remote, addrlen) < 0)
		  {
		    msg_out(crit, "UDP: error sending IPv6 request to server\n");
		    break;
		  }
	      }
	  }
	else
	  {
	    /* possible server response */
	    /* TODO: Is it neccessary to distinguish IPv4/v6 ? */

	    bzero(&outbuf, sizeof(outbuf));
	    udpmsg = (struct socks_udpmsg*)outbuf;

	    if (sender.ss_family == AF_INET6)
	      {
		struct sockaddr_in6 remote;
		struct sockaddr_in6 *udp_ip6 = NULL;
		struct sockaddr_in6 *sender_ip6 = NULL;
		
		bzero(&remote, sizeof(remote));
		udp_ip6 = (struct sockaddr_in6*)udp;
		sender_ip6 = (struct sockaddr_in6*)&sender;

		udpmsg->rsv  = 0;
		udpmsg->frag = 0;
		udpmsg->atyp = S5ATIPV6;
		/* this part is unclear - do I have to use _my_ address or the original? */
		udpmsg->_addr._ip6.addr = sender_ip6->sin6_addr;
		udpmsg->_addr._ip6.port = sender_ip6->sin6_port;

		memcpy(&outbuf[SOCKS_UDPMSG_V6_SIZE(udpmsg)], buf, recvlen);
		remote.sin6_addr    = udp_ip6->sin6_addr;
		remote.sin6_port    = udp_ip6->sin6_port;
		remote.sin6_family  = AF_INET6;
		remote.sin6_len     = sizeof(remote);
		addrlen = sizeof(remote);

		if (learn_client == 1)
		  {
		    msg_out(warn, "UDP: dropping server message - client is unknown!\n");
		    continue;
		  }
		if (sendto(ss, outbuf, recvlen + SOCKS_UDPMSG_V6_SIZE(udpmsg),
			   0, (struct sockaddr*)&remote, addrlen) < 0)
		  {
		    msg_out(crit, "UDP: error sending IPv6 response to client\n");
		    break;
		  }
	      }
	    else
	      {
		struct sockaddr_in remote;
		struct sockaddr_in *udp_ip4 = NULL;
		struct sockaddr_in *sender_ip4 = NULL;
		
		bzero(&remote, sizeof(remote));
		udp_ip4 = (struct sockaddr_in*)udp;
		sender_ip4 = (struct sockaddr_in*)&sender;

		udpmsg->rsv  = 0;
		udpmsg->frag = 0;
		udpmsg->atyp = S5ATIPV4;
		/* this part is unclear - do I have to use _my_ address or the original? */
		udpmsg->_addr._ip4.addr = sender_ip4->sin_addr.s_addr;
		udpmsg->_addr._ip4.addr = sender_ip4->sin_port;

		memcpy(&outbuf[SOCKS_UDPMSG_V4_SIZE(udpmsg)], buf, recvlen);
		remote.sin_addr.s_addr = udp_ip4->sin_addr.s_addr;
		remote.sin_port        = udp_ip4->sin_port;
		remote.sin_family      = AF_INET;
		remote.sin_len         = sizeof(remote);
		addrlen = sizeof(remote);

		if (learn_client == 1)
		  {
		    msg_out(warn, "UDP: dropping server message - client is unknown!\n");
		    continue;
		  }
		if (sendto(ss, outbuf, recvlen + SOCKS_UDPMSG_V4_SIZE(udpmsg),
			   0, (struct sockaddr*)&remote, addrlen) < 0)
		  {
		    msg_out(crit, "UDP: error sending IPv4 response to client\n");
		    break;
		  }
	      }
	  }
      }

    close(ss);
    close(cs);

#ifdef IPHONE_OS
    pthread_mutex_lock(&stat_lock);
    stat_connections--;
    pthread_mutex_unlock(&stat_lock);
#endif
}
ws_ctx_t *do_handshake(int sock) {
    char handshake[4096], response[4096], sha1[29], trailer[17];
    char *scheme, *pre;
    headers_t *headers;
    int len, ret, i, offset;
    ws_ctx_t * ws_ctx;

    // Peek, but don't read the data
    len = recv(sock, handshake, 1024, MSG_PEEK);
    handshake[len] = 0;
    if (len == 0) {
        handler_msg("ignoring empty handshake\n");
        return NULL;
    } else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) {
        len = recv(sock, handshake, 1024, 0);
        handshake[len] = 0;
        handler_msg("sending flash policy response\n");
        send(sock, POLICY_RESPONSE, sizeof(POLICY_RESPONSE), 0);
        return NULL;
    } else if ((bcmp(handshake, "\x16", 1) == 0) ||
               (bcmp(handshake, "\x80", 1) == 0)) {
        // SSL
        if (!settings.cert) {
            handler_msg("SSL connection but no cert specified\n");
            return NULL;
        } else if (access(settings.cert, R_OK) != 0) {
            handler_msg("SSL connection but '%s' not found\n",
                        settings.cert);
            return NULL;
        }
        ws_ctx = alloc_ws_ctx();
        ws_socket_ssl(ws_ctx, sock, settings.cert, settings.key);
        if (! ws_ctx) { return NULL; }
        scheme = "wss";
        handler_msg("using SSL socket\n");
    } else if (settings.ssl_only) {
        handler_msg("non-SSL connection disallowed\n");
        return NULL;
    } else {
        ws_ctx = alloc_ws_ctx();
        ws_socket(ws_ctx, sock);
        if (! ws_ctx) { return NULL; }
        scheme = "ws";
        handler_msg("using plain (not SSL) socket\n");
    }
    offset = 0;
    for (i = 0; i < 10; i++) {
        len = ws_recv(ws_ctx, handshake+offset, 4096);
        if (len == 0) {
            handler_emsg("Client closed during handshake\n");
            return NULL;
        }
        offset += len;
        handshake[offset] = 0;
        if (strstr(handshake, "\r\n\r\n")) {
            break;
        }
        usleep(10);
    }

    //handler_msg("handshake: %s\n", handshake);
    if (!parse_handshake(ws_ctx, handshake)) {
        handler_emsg("Invalid WS request\n");
        return NULL;
    }

    headers = ws_ctx->headers;
    if (ws_ctx->hybi > 0) {
        handler_msg("using protocol HyBi/IETF 6455 %d\n", ws_ctx->hybi);
        gen_sha1(headers, sha1);
        sprintf(response, SERVER_HANDSHAKE_HYBI, sha1, "base64");
    } else {
        if (ws_ctx->hixie == 76) {
            handler_msg("using protocol Hixie 76\n");
            gen_md5(headers, trailer);
            pre = "Sec-";
        } else {
            handler_msg("using protocol Hixie 75\n");
            trailer[0] = '\0';
            pre = "";
        }
        sprintf(response, SERVER_HANDSHAKE_HIXIE, pre, headers->origin, pre, scheme,
                headers->host, headers->path, pre, "base64", trailer);
    }
    
    //handler_msg("response: %s\n", response);
    ws_send(ws_ctx, response, strlen(response));

    return ws_ctx;
}
int parse_handshake(ws_ctx_t *ws_ctx, char *handshake) {
    char *start, *end;
    headers_t *headers = ws_ctx->headers;

    headers->key1[0] = '\0';
    headers->key2[0] = '\0';
    headers->key3[0] = '\0';
    
    if ((strlen(handshake) < 92) || (bcmp(handshake, "GET ", 4) != 0)) {
        return 0;
    }
    start = handshake+4;
    end = strstr(start, " HTTP/1.1");
    if (!end) { return 0; }
    strncpy(headers->path, start, end-start);
    headers->path[end-start] = '\0';

    start = strstr(handshake, "\r\nHost: ");
    if (!start) { return 0; }
    start += 8;
    end = strstr(start, "\r\n");
    strncpy(headers->host, start, end-start);
    headers->host[end-start] = '\0';

    headers->origin[0] = '\0';
    start = strstr(handshake, "\r\nOrigin: ");
    if (start) {
        start += 10;
    } else {
        start = strstr(handshake, "\r\nSec-WebSocket-Origin: ");
        if (!start) { return 0; }
        start += 24;
    }
    end = strstr(start, "\r\n");
    strncpy(headers->origin, start, end-start);
    headers->origin[end-start] = '\0';
   
    start = strstr(handshake, "\r\nSec-WebSocket-Version: ");
    if (start) {
        // HyBi/RFC 6455
        start += 25;
        end = strstr(start, "\r\n");
        strncpy(headers->version, start, end-start);
        headers->version[end-start] = '\0';
        ws_ctx->hixie = 0;
        ws_ctx->hybi = strtol(headers->version, NULL, 10);

        start = strstr(handshake, "\r\nSec-WebSocket-Key: ");
        if (!start) { return 0; }
        start += 21;
        end = strstr(start, "\r\n");
        strncpy(headers->key1, start, end-start);
        headers->key1[end-start] = '\0';
   
        start = strstr(handshake, "\r\nConnection: ");
        if (!start) { return 0; }
        start += 14;
        end = strstr(start, "\r\n");
        strncpy(headers->connection, start, end-start);
        headers->connection[end-start] = '\0';
   
        start = strstr(handshake, "\r\nSec-WebSocket-Protocol: ");
        if (!start) { return 0; }
        start += 26;
        end = strstr(start, "\r\n");
        strncpy(headers->protocols, start, end-start);
        headers->protocols[end-start] = '\0';
    } else {
        // Hixie 75 or 76
        ws_ctx->hybi = 0;

        start = strstr(handshake, "\r\n\r\n");
        if (!start) { return 0; }
        start += 4;
        if (strlen(start) == 8) {
            ws_ctx->hixie = 76;
            strncpy(headers->key3, start, 8);
            headers->key3[8] = '\0';

            start = strstr(handshake, "\r\nSec-WebSocket-Key1: ");
            if (!start) { return 0; }
            start += 22;
            end = strstr(start, "\r\n");
            strncpy(headers->key1, start, end-start);
            headers->key1[end-start] = '\0';
        
            start = strstr(handshake, "\r\nSec-WebSocket-Key2: ");
            if (!start) { return 0; }
            start += 22;
            end = strstr(start, "\r\n");
            strncpy(headers->key2, start, end-start);
            headers->key2[end-start] = '\0';
        } else {
            ws_ctx->hixie = 75;
        }

    }

    return 1;
}
Beispiel #15
0
int
gptfind(const uuid_t *uuid, struct dsk *dskp, int part)
{
	struct gpt_ent *ent;
	int firsttry;

	if (part >= 0) {
		if (part == 0 || part > gpthdr->hdr_entries) {
			printf("%s: invalid partition index\n", BOOTPROG);
			return (-1);
		}
		ent = &gpttable[part - 1];
		if (bcmp(&ent->ent_type, uuid, sizeof(uuid_t)) != 0) {
			printf("%s: specified partition is not UFS\n",
			    BOOTPROG);
			return (-1);
		}
		curent = part - 1;
		goto found;
	}

	firsttry = (curent == -1);
	curent++;
	if (curent >= gpthdr->hdr_entries) {
		curent = gpthdr->hdr_entries;
		return (-1);
	}
	if (bootonce) {
		/*
		 * First look for partition with both GPT_ENT_ATTR_BOOTME and
		 * GPT_ENT_ATTR_BOOTONCE flags.
		 */
		for (; curent < gpthdr->hdr_entries; curent++) {
			ent = &gpttable[curent];
			if (bcmp(&ent->ent_type, uuid, sizeof(uuid_t)) != 0)
				continue;
			if (!(ent->ent_attr & GPT_ENT_ATTR_BOOTME))
				continue;
			if (!(ent->ent_attr & GPT_ENT_ATTR_BOOTONCE))
				continue;
			/* Ok, found one. */
			goto found;
		}
		bootonce = 0;
		curent = 0;
	}
	for (; curent < gpthdr->hdr_entries; curent++) {
		ent = &gpttable[curent];
		if (bcmp(&ent->ent_type, uuid, sizeof(uuid_t)) != 0)
			continue;
		if (!(ent->ent_attr & GPT_ENT_ATTR_BOOTME))
			continue;
		if (ent->ent_attr & GPT_ENT_ATTR_BOOTONCE)
			continue;
		/* Ok, found one. */
		goto found;
	}
	if (firsttry) {
		/*
		 * No partition with BOOTME flag was found, try to boot from
		 * first UFS partition.
		 */
		for (curent = 0; curent < gpthdr->hdr_entries; curent++) {
			ent = &gpttable[curent];
			if (bcmp(&ent->ent_type, uuid, sizeof(uuid_t)) != 0)
				continue;
			/* Ok, found one. */
			goto found;
		}
	}
	return (-1);
found:
	dskp->part = curent + 1;
	ent = &gpttable[curent];
	dskp->start = ent->ent_lba_start;
	if (ent->ent_attr & GPT_ENT_ATTR_BOOTONCE) {
		/*
		 * Clear BOOTME, but leave BOOTONCE set before trying to
		 * boot from this partition.
		 */
		if (hdr_primary_lba > 0) {
			table_primary[curent].ent_attr &= ~GPT_ENT_ATTR_BOOTME;
			gptupdate("primary", dskp, &hdr_primary, table_primary);
		}
		if (hdr_backup_lba > 0) {
			table_backup[curent].ent_attr &= ~GPT_ENT_ATTR_BOOTME;
			gptupdate("backup", dskp, &hdr_backup, table_backup);
		}
	}
	return (0);
}
Beispiel #16
0
int
esp4_input(struct mbuf **mp, int *offp, int proto)
{
	int off;
	struct ip *ip;
	struct esp *esp;
	struct esptail esptail;
	struct mbuf *m;
	u_int32_t spi;
	struct secasvar *sav = NULL;
	size_t taillen;
	u_int16_t nxt;
	const struct esp_algorithm *algo;
	int ivlen;
	size_t hlen;
	size_t esplen;

	off = *offp;
	m = *mp;
	*mp = NULL;

	/* sanity check for alignment. */
	if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
		ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
			"(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
		ipsecstat.in_inval++;
		goto bad;
	}

	if (m->m_len < off + ESPMAXLEN) {
		m = m_pullup(m, off + ESPMAXLEN);
		if (!m) {
			ipseclog((LOG_DEBUG,
			    "IPv4 ESP input: can't pullup in esp4_input\n"));
			ipsecstat.in_inval++;
			goto bad;
		}
	}

	ip = mtod(m, struct ip *);
	esp = (struct esp *)(((u_int8_t *)ip) + off);
#ifdef _IP_VHL
	hlen = IP_VHL_HL(ip->ip_vhl) << 2;
#else
	hlen = ip->ip_hl << 2;
#endif

	/* find the sassoc. */
	spi = esp->esp_spi;

	if ((sav = key_allocsa(AF_INET,
	                      (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
	                      IPPROTO_ESP, spi)) == 0) {
		ipseclog((LOG_WARNING,
		    "IPv4 ESP input: no key association found for spi %u\n",
		    (u_int32_t)ntohl(spi)));
		ipsecstat.in_nosa++;
		goto bad;
	}
	KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
		kprintf("DP esp4_input called to allocate SA:%p\n", sav));
	if (sav->state != SADB_SASTATE_MATURE
	 && sav->state != SADB_SASTATE_DYING) {
		ipseclog((LOG_DEBUG,
		    "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
		    (u_int32_t)ntohl(spi)));
		ipsecstat.in_badspi++;
		goto bad;
	}
	algo = esp_algorithm_lookup(sav->alg_enc);
	if (!algo) {
		ipseclog((LOG_DEBUG, "IPv4 ESP input: "
		    "unsupported encryption algorithm for spi %u\n",
		    (u_int32_t)ntohl(spi)));
		ipsecstat.in_badspi++;
		goto bad;
	}

	/* check if we have proper ivlen information */
	ivlen = sav->ivlen;
	if (ivlen < 0) {
		ipseclog((LOG_ERR, "improper ivlen in IPv4 ESP input: %s %s\n",
		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
		ipsecstat.in_inval++;
		goto bad;
	}

	if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
	 && (sav->alg_auth && sav->key_auth)))
		goto noreplaycheck;

	if (sav->alg_auth == SADB_X_AALG_NULL ||
	    sav->alg_auth == SADB_AALG_NONE)
		goto noreplaycheck;

	/*
	 * check for sequence number.
	 */
	if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
		; /* okey */
	else {
		ipsecstat.in_espreplay++;
		ipseclog((LOG_WARNING,
		    "replay packet in IPv4 ESP input: %s %s\n",
		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
		goto bad;
	}

	/* check ICV */
    {
	u_char sum0[AH_MAXSUMSIZE];
	u_char sum[AH_MAXSUMSIZE];
	const struct ah_algorithm *sumalgo;
	size_t siz;

	sumalgo = ah_algorithm_lookup(sav->alg_auth);
	if (!sumalgo)
		goto noreplaycheck;
	siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
	if (m->m_pkthdr.len < off + ESPMAXLEN + siz) {
		ipsecstat.in_inval++;
		goto bad;
	}
	if (AH_MAXSUMSIZE < siz) {
		ipseclog((LOG_DEBUG,
		    "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
		    (u_long)siz));
		ipsecstat.in_inval++;
		goto bad;
	}

	m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);

	if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
		ipsecstat.in_espauthfail++;
		goto bad;
	}

	if (bcmp(sum0, sum, siz) != 0) {
		ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
		ipsecstat.in_espauthfail++;
		goto bad;
	}

	/* strip off the authentication data */
	m_adj(m, -siz);
	ip = mtod(m, struct ip *);
#ifdef IPLEN_FLIPPED
	ip->ip_len = ip->ip_len - siz;
#else
	ip->ip_len = htons(ntohs(ip->ip_len) - siz);
#endif
	m->m_flags |= M_AUTHIPDGM;
	ipsecstat.in_espauthsucc++;
    }

	/*
	 * update sequence number.
	 */
	if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
		if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
			ipsecstat.in_espreplay++;
			goto bad;
		}
	}

noreplaycheck:

	/* process main esp header. */
	if (sav->flags & SADB_X_EXT_OLD) {
		/* RFC 1827 */
		esplen = sizeof(struct esp);
	} else {
		/* RFC 2406 */
		if (sav->flags & SADB_X_EXT_DERIV)
			esplen = sizeof(struct esp);
		else
			esplen = sizeof(struct newesp);
	}

	if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
		ipseclog((LOG_WARNING,
		    "IPv4 ESP input: packet too short\n"));
		ipsecstat.in_inval++;
		goto bad;
	}

	if (m->m_len < off + esplen + ivlen) {
		m = m_pullup(m, off + esplen + ivlen);
		if (!m) {
			ipseclog((LOG_DEBUG,
			    "IPv4 ESP input: can't pullup in esp4_input\n"));
			ipsecstat.in_inval++;
			goto bad;
		}
	}

	/*
	 * pre-compute and cache intermediate key
	 */
	if (esp_schedule(algo, sav) != 0) {
		ipsecstat.in_inval++;
		goto bad;
	}

	/*
	 * decrypt the packet.
	 */
	if (!algo->decrypt)
		panic("internal error: no decrypt function");
	if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
		/* m is already freed */
		m = NULL;
		ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
		    ipsec_logsastr(sav)));
		ipsecstat.in_inval++;
		goto bad;
	}
	ipsecstat.in_esphist[sav->alg_enc]++;

	m->m_flags |= M_DECRYPTED;

	/*
	 * find the trailer of the ESP.
	 */
	m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
	     (caddr_t)&esptail);
	nxt = esptail.esp_nxt;
	taillen = esptail.esp_padlen + sizeof(esptail);

	if (m->m_pkthdr.len < taillen ||
	    m->m_pkthdr.len - taillen < off + esplen + ivlen + sizeof(esptail)) {
		ipseclog((LOG_WARNING,
		    "bad pad length in IPv4 ESP input: %s %s\n",
		    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
		ipsecstat.in_inval++;
		goto bad;
	}

	/* strip off the trailing pad area. */
	m_adj(m, -taillen);

#ifdef IPLEN_FLIPPED
	ip->ip_len = ip->ip_len - taillen;
#else
	ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
#endif

	/* was it transmitted over the IPsec tunnel SA? */
	if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
		/*
		 * strip off all the headers that precedes ESP header.
		 *	IP4 xx ESP IP4' payload -> IP4' payload
		 *
		 * XXX more sanity checks
		 * XXX relationship with gif?
		 */
		u_int8_t tos;

		tos = ip->ip_tos;
		m_adj(m, off + esplen + ivlen);
		if (m->m_len < sizeof(*ip)) {
			m = m_pullup(m, sizeof(*ip));
			if (!m) {
				ipsecstat.in_inval++;
				goto bad;
			}
		}
		ip = mtod(m, struct ip *);
		/* ECN consideration. */
		ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
		if (!key_checktunnelsanity(sav, AF_INET,
			    (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
			ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
			    "in IPv4 ESP input: %s %s\n",
			    ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
			ipsecstat.in_inval++;
			goto bad;
		}

		key_sa_recordxfer(sav, m);
		if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
		    ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
			ipsecstat.in_nomem++;
			goto bad;
		}

		if (netisr_queue(NETISR_IP, m)) {
			ipsecstat.in_inval++;
			m = NULL;
			goto bad;
		}

		nxt = IPPROTO_DONE;
	} else {
Beispiel #17
0
int
test_decode(void *code, int k, int index[], int sz, char *s)
{
    int errors;
    int reconstruct = 0 ;
    int item, i ;

    static int prev_k = 0, prev_sz = 0;
    static u_char **d_original = NULL, **d_src = NULL ;

    if (sz < 1 || sz > 8192) {
	fprintf(stderr, "test_decode: size %d invalid, must be 1..8K\n",
		sz);
	return 1 ;
    }
    if (k < 1 || k > GF_SIZE + 1) {
	fprintf(stderr, "test_decode: k %d invalid, must be 1..%d\n",
		k, GF_SIZE + 1 );
	return 2 ;
    }
    if (prev_k != k || prev_sz != sz) {
	if (d_original != NULL) {
	    for (i = 0 ; i < prev_k ; i++ ) {
		free(d_original[i]);
		free(d_src[i]);
	    }
	    free(d_original);
	    free(d_src);
	    d_original = NULL ;
	    d_src = NULL ;
	}
    }
    prev_k = k ;
    prev_sz = sz ;
    if (d_original == NULL) {
	d_original = my_malloc(k * sizeof(void *), "d_original ptr");
	d_src = my_malloc(k * sizeof(void *), "d_src ptr");

	for (i = 0 ; i < k ; i++ ) {
	    d_original[i] = my_malloc(sz, "d_original data");
	    d_src[i] = my_malloc(sz, "d_src data");
	}
	/*
	 * build sample data
	 */
	for (i = 0 ; i < k ; i++ ) {
	    for (item=0; item < sz; item++)
		d_original[i][item] = ((item ^ i) + 3) & GF_SIZE;
	}
    }

    errors = 0 ;

    for( i = 0 ; i < k ; i++ )
	if (index[i] >= k ) reconstruct ++ ;

    TICK(ticks[2]);
    for( i = 0 ; i < k ; i++ )
	fec_encode(code, d_original, d_src[i], index[i], sz );
    TOCK(ticks[2]);

    TICK(ticks[1]);
    if (fec_decode(code, d_src, index, sz)) {
	fprintf(stderr, "detected singular matrix for %s  \n", s);
	return 1 ;
    }
    TOCK(ticks[1]);

    for (i=0; i<k; i++)
	if (bcmp(d_original[i], d_src[i], sz )) {
	    errors++;
	    fprintf(stderr, "error reconstructing block %d\n", i);
	}
    if (errors)
	fprintf(stderr, "Errors reconstructing %d blocks out of %d\n",
	    errors, k);

    fprintf(stderr,
	"  k %3d, l %3d  c_enc %10.6f MB/s c_dec %10.6f MB/s     \r",
	k, reconstruct,
	(double)(k * sz * reconstruct)/(double)ticks[2],
	(double)(k * sz * reconstruct)/(double)ticks[1]);
    return errors ;
}
Beispiel #18
0
/*
 * When we search a directory the blocks containing directory entries are
 * read and examined.  The directory entries contain information that would
 * normally be in the inode of a unix filesystem.  This means that some of
 * a directory's contents may also be in memory resident denodes (sort of
 * an inode).  This can cause problems if we are searching while some other
 * process is modifying a directory.  To prevent one process from accessing
 * incompletely modified directory information we depend upon being the
 * sole owner of a directory block.  bread/brelse provide this service.
 * This being the case, when a process modifies a directory it must first
 * acquire the disk block that contains the directory entry to be modified.
 * Then update the disk block and the denode, and then write the disk block
 * out to disk.  This way disk blocks containing directory entries and in
 * memory denode's will be in synch.
 */
static int
msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp,
    struct componentname *cnp, u_int64_t *dd_inum)
{
	struct mbnambuf nb;
	daddr_t bn;
	int error;
	int slotcount;
	int slotoffset = 0;
	int frcn;
	u_long cluster;
	int blkoff;
	int diroff;
	int blsize;
	int isadir;		/* ~0 if found direntry is a directory	 */
	u_long scn;		/* starting cluster number		 */
	struct vnode *pdp;
	struct denode *dp;
	struct denode *tdp;
	struct msdosfsmount *pmp;
	struct buf *bp = 0;
	struct direntry *dep = NULL;
	u_char dosfilename[12];
	int flags = cnp->cn_flags;
	int nameiop = cnp->cn_nameiop;
	int unlen;
	u_int64_t inode1;

	int wincnt = 1;
	int chksum = -1, chksum_ok;
	int olddos = 1;

#ifdef MSDOSFS_DEBUG
	printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr);
#endif
	dp = VTODE(vdp);
	pmp = dp->de_pmp;
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n",
	    vdp, dp, dp->de_Attributes);
#endif

 restart:
	if (vpp != NULL)
		*vpp = NULL;
	/*
	 * If they are going after the . or .. entry in the root directory,
	 * they won't find it.  DOS filesystems don't have them in the root
	 * directory.  So, we fake it. deget() is in on this scam too.
	 */
	if ((vdp->v_vflag & VV_ROOT) && cnp->cn_nameptr[0] == '.' &&
	    (cnp->cn_namelen == 1 ||
		(cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) {
		isadir = ATTR_DIRECTORY;
		scn = MSDOSFSROOT;
#ifdef MSDOSFS_DEBUG
		printf("msdosfs_lookup(): looking for . or .. in root directory\n");
#endif
		cluster = MSDOSFSROOT;
		blkoff = MSDOSFSROOT_OFS;
		goto foundroot;
	}

	switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename,
	    cnp->cn_namelen, 0, pmp)) {
	case 0:
		return (EINVAL);
	case 1:
		break;
	case 2:
		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
		    cnp->cn_namelen, pmp) + 1;
		break;
	case 3:
		olddos = 0;
		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
		    cnp->cn_namelen, pmp) + 1;
		break;
	}
	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) {
		wincnt = 1;
		olddos = 1;
	}
	unlen = winLenFixup(cnp->cn_nameptr, cnp->cn_namelen);

	/*
	 * Suppress search for slots unless creating
	 * file and at end of pathname, in which case
	 * we watch for a place to put the new file in
	 * case it doesn't already exist.
	 */
	slotcount = wincnt;
	if ((nameiop == CREATE || nameiop == RENAME) &&
	    (flags & ISLASTCN))
		slotcount = 0;

#ifdef MSDOSFS_DEBUG
	printf("msdosfs_lookup(): dos version of filename %s, length %ld\n",
	    dosfilename, cnp->cn_namelen);
#endif
	/*
	 * Search the directory pointed at by vdp for the name pointed at
	 * by cnp->cn_nameptr.
	 */
	tdp = NULL;
	mbnambuf_init(&nb);
	/*
	 * The outer loop ranges over the clusters that make up the
	 * directory.  Note that the root directory is different from all
	 * other directories.  It has a fixed number of blocks that are not
	 * part of the pool of allocatable clusters.  So, we treat it a
	 * little differently. The root directory starts at "cluster" 0.
	 */
	diroff = 0;
	for (frcn = 0;; frcn++) {
		error = pcbmap(dp, frcn, &bn, &cluster, &blsize);
		if (error) {
			if (error == E2BIG)
				break;
			return (error);
		}
		error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}
		for (blkoff = 0; blkoff < blsize;
		     blkoff += sizeof(struct direntry),
		     diroff += sizeof(struct direntry)) {
			dep = (struct direntry *)(bp->b_data + blkoff);
			/*
			 * If the slot is empty and we are still looking
			 * for an empty then remember this one.  If the
			 * slot is not empty then check to see if it
			 * matches what we are looking for.  If the slot
			 * has never been filled with anything, then the
			 * remainder of the directory has never been used,
			 * so there is no point in searching it.
			 */
			if (dep->deName[0] == SLOT_EMPTY ||
			    dep->deName[0] == SLOT_DELETED) {
				/*
				 * Drop memory of previous long matches
				 */
				chksum = -1;
				mbnambuf_init(&nb);

				if (slotcount < wincnt) {
					slotcount++;
					slotoffset = diroff;
				}
				if (dep->deName[0] == SLOT_EMPTY) {
					brelse(bp);
					goto notfound;
				}
			} else {
				/*
				 * If there wasn't enough space for our winentries,
				 * forget about the empty space
				 */
				if (slotcount < wincnt)
					slotcount = 0;

				/*
				 * Check for Win95 long filename entry
				 */
				if (dep->deAttributes == ATTR_WIN95) {
					if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
						continue;

					chksum = win2unixfn(&nb,
					    (struct winentry *)dep, chksum,
					    pmp);
					continue;
				}

				chksum = winChkName(&nb,
				    (const u_char *)cnp->cn_nameptr, unlen,
				    chksum, pmp);
				if (chksum == -2) {
					chksum = -1;
					continue;
				}

				/*
				 * Ignore volume labels (anywhere, not just
				 * the root directory).
				 */
				if (dep->deAttributes & ATTR_VOLUME) {
					chksum = -1;
					continue;
				}

				/*
				 * Check for a checksum or name match
				 */
				chksum_ok = (chksum == winChksum(dep->deName));
				if (!chksum_ok
				    && (!olddos || bcmp(dosfilename, dep->deName, 11))) {
					chksum = -1;
					continue;
				}
#ifdef MSDOSFS_DEBUG
				printf("msdosfs_lookup(): match blkoff %d, diroff %d\n",
				    blkoff, diroff);
#endif
				/*
				 * Remember where this directory
				 * entry came from for whoever did
				 * this lookup.
				 */
				dp->de_fndoffset = diroff;
				if (chksum_ok && nameiop == RENAME) {
					/*
					 * Target had correct long name
					 * directory entries, reuse them
					 * as needed.
					 */
					dp->de_fndcnt = wincnt - 1;
				} else {
					/*
					 * Long name directory entries
					 * not present or corrupt, can only
					 * reuse dos directory entry.
					 */
					dp->de_fndcnt = 0;
				}

				goto found;
			}
		}	/* for (blkoff = 0; .... */
		/*
		 * Release the buffer holding the directory cluster just
		 * searched.
		 */
		brelse(bp);
	}	/* for (frcn = 0; ; frcn++) */

notfound:
	/*
	 * We hold no disk buffers at this point.
	 */

	/*
	 * Fixup the slot description to point to the place where
	 * we might put the new DOS direntry (putting the Win95
	 * long name entries before that)
	 */
	if (!slotcount) {
		slotcount = 1;
		slotoffset = diroff;
	}
	if (wincnt > slotcount)
		slotoffset += sizeof(struct direntry) * (wincnt - slotcount);

	/*
	 * If we get here we didn't find the entry we were looking for. But
	 * that's ok if we are creating or renaming and are at the end of
	 * the pathname and the directory hasn't been removed.
	 */
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_lookup(): op %d, refcnt %ld\n",
	    nameiop, dp->de_refcnt);
	printf("               slotcount %d, slotoffset %d\n",
	       slotcount, slotoffset);
#endif
	if ((nameiop == CREATE || nameiop == RENAME) &&
	    (flags & ISLASTCN) && dp->de_refcnt != 0) {
		/*
		 * Access for write is interpreted as allowing
		 * creation of files in the directory.
		 */
		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread);
		if (error)
			return (error);
		/*
		 * Return an indication of where the new directory
		 * entry should be put.
		 */
		dp->de_fndoffset = slotoffset;
		dp->de_fndcnt = wincnt - 1;

		/*
		 * We return with the directory locked, so that
		 * the parameters we set up above will still be
		 * valid if we actually decide to do a direnter().
		 * We return ni_vp == NULL to indicate that the entry
		 * does not currently exist; we leave a pointer to
		 * the (locked) directory inode in ndp->ni_dvp.
		 * The pathname buffer is saved so that the name
		 * can be obtained later.
		 *
		 * NB - if the directory is unlocked, then this
		 * information cannot be used.
		 */
		cnp->cn_flags |= SAVENAME;
		return (EJUSTRETURN);
	}
#if 0
	/*
	 * Insert name into cache (as non-existent) if appropriate.
	 *
	 * XXX Negative caching is broken for msdosfs because the name
	 * cache doesn't understand peculiarities such as case insensitivity
	 * and 8.3 filenames.  Hence, it may not invalidate all negative
	 * entries if a file with this name is later created.
	 */
	if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
		cache_enter(vdp, *vpp, cnp);
#endif
	return (ENOENT);

found:
	/*
	 * NOTE:  We still have the buffer with matched directory entry at
	 * this point.
	 */
	isadir = dep->deAttributes & ATTR_DIRECTORY;
	scn = getushort(dep->deStartCluster);
	if (FAT32(pmp)) {
		scn |= getushort(dep->deHighClust) << 16;
		if (scn == pmp->pm_rootdirblk) {
			/*
			 * There should actually be 0 here.
			 * Just ignore the error.
			 */
			scn = MSDOSFSROOT;
		}
	}

	if (isadir) {
		cluster = scn;
		if (cluster == MSDOSFSROOT)
			blkoff = MSDOSFSROOT_OFS;
		else
			blkoff = 0;
	} else if (cluster == MSDOSFSROOT)
		blkoff = diroff;

	/*
	 * Now release buf to allow deget to read the entry again.
	 * Reserving it here and giving it to deget could result
	 * in a deadlock.
	 */
	brelse(bp);
	bp = 0;
	
foundroot:
	/*
	 * If we entered at foundroot, then we are looking for the . or ..
	 * entry of the filesystems root directory.  isadir and scn were
	 * setup before jumping here.  And, bp is already null.
	 */
	if (FAT32(pmp) && scn == MSDOSFSROOT)
		scn = pmp->pm_rootdirblk;

	if (dd_inum != NULL) {
		*dd_inum = (uint64_t)pmp->pm_bpcluster * scn + blkoff;
		return (0);
	}

	/*
	 * If deleting, and at end of pathname, return
	 * parameters which can be used to remove file.
	 */
	if (nameiop == DELETE && (flags & ISLASTCN)) {
		/*
		 * Don't allow deleting the root.
		 */
		if (blkoff == MSDOSFSROOT_OFS)
			return (EBUSY);

		/*
		 * Write access to directory required to delete files.
		 */
		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread);
		if (error)
			return (error);

		/*
		 * Return pointer to current entry in dp->i_offset.
		 * Save directory inode pointer in ndp->ni_dvp for dirremove().
		 */
		if (dp->de_StartCluster == scn && isadir) {	/* "." */
			VREF(vdp);
			*vpp = vdp;
			return (0);
		}
		error = deget(pmp, cluster, blkoff, &tdp);
		if (error)
			return (error);
		*vpp = DETOV(tdp);
		return (0);
	}

	/*
	 * If rewriting (RENAME), return the inode and the
	 * information required to rewrite the present directory
	 * Must get inode of directory entry to verify it's a
	 * regular file, or empty directory.
	 */
	if (nameiop == RENAME && (flags & ISLASTCN)) {
		if (blkoff == MSDOSFSROOT_OFS)
			return (EBUSY);

		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread);
		if (error)
			return (error);

		/*
		 * Careful about locking second inode.
		 * This can only occur if the target is ".".
		 */
		if (dp->de_StartCluster == scn && isadir)
			return (EISDIR);

		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
			return (error);
		*vpp = DETOV(tdp);
		cnp->cn_flags |= SAVENAME;
		return (0);
	}

	/*
	 * Step through the translation in the name.  We do not `vput' the
	 * directory because we may need it again if a symbolic link
	 * is relative to the current directory.  Instead we save it
	 * unlocked as "pdp".  We must get the target inode before unlocking
	 * the directory to insure that the inode will not be removed
	 * before we get it.  We prevent deadlock by always fetching
	 * inodes from the root, moving down the directory tree. Thus
	 * when following backward pointers ".." we must unlock the
	 * parent directory before getting the requested directory.
	 */
	pdp = vdp;
	if (flags & ISDOTDOT) {
		error = msdosfs_deget_dotdot(pdp, cluster, blkoff, vpp);
		if (error) {
			*vpp = NULL;
			return (error);
		}
		/*
		 * Recheck that ".." still points to the inode we
		 * looked up before pdp lock was dropped.
		 */
		error = msdosfs_lookup_(pdp, NULL, cnp, &inode1);
		if (error) {
			vput(*vpp);
			*vpp = NULL;
			return (error);
		}
		if (VTODE(*vpp)->de_inode != inode1) {
			vput(*vpp);
			goto restart;
		}
	} else if (dp->de_StartCluster == scn && isadir) {
		VREF(vdp);	/* we want ourself, ie "." */
		*vpp = vdp;
	} else {
		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
			return (error);
		*vpp = DETOV(tdp);
	}

	/*
	 * Insert name into cache if appropriate.
	 */
	if (cnp->cn_flags & MAKEENTRY)
		cache_enter(vdp, *vpp, cnp);
	return (0);
}
Beispiel #19
0
static int
ed_probe_gwether(device_t dev)
{
	int     x, i, msize = 0;
	bus_size_t mstart = 0;
	char    pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE], tbuf[ED_PAGE_SIZE];
	struct ed_softc *sc = device_get_softc(dev);

	for (i = 0; i < ED_PAGE_SIZE; i++)
		pbuf0[i] = 0;

	/* Clear all the memory. */
	for (x = 1; x < 256; x++)
		ed_pio_writemem(sc, pbuf0, x * 256, ED_PAGE_SIZE);

	/* Search for the start of RAM. */
	for (x = 1; x < 256; x++) {
		ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
		if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
			for (i = 0; i < ED_PAGE_SIZE; i++)
				pbuf[i] = 255 - x;
			ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
			ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
			if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) {
				mstart = x * ED_PAGE_SIZE;
				msize = ED_PAGE_SIZE;
				break;
			}
		}
	}
	if (mstart == 0) {
		device_printf(dev, "Cannot find start of RAM.\n");
		return (ENXIO);
	}

	/* Probe the size of RAM. */
	for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) {
		ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
		if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
			for (i = 0; i < ED_PAGE_SIZE; i++)
				pbuf[i] = 255 - x;
			ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE);
			ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE);
			if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0)
				msize += ED_PAGE_SIZE;
			else {
				break;
			}
		} else {
			break;
		}
	}

	if (msize == 0) {
		device_printf(dev,
		    "Cannot find any RAM, start : %d, x = %d.\n",
		    (int)mstart, x);
		return (ENXIO);
	}
	if (bootverbose)
		device_printf(dev,
		    "RAM start at %d, size : %d.\n", (int)mstart, msize);

	sc->mem_size = msize;
	sc->mem_start = mstart;
	sc->mem_end = msize + mstart;
	sc->tx_page_start = mstart / ED_PAGE_SIZE;
	return 0;
}
static int
dskread(void *buf, daddr_t lba, unsigned nblk)
{
    struct gpt_hdr hdr;
    struct gpt_ent *ent;
    char *sec;
    daddr_t slba, elba;
    int part, entries_per_sec;

    if (!dsk_meta) {
	/* Read and verify GPT. */
	sec = dmadat->secbuf;
	dsk.start = 0;
	if (drvread(sec, 1, 1))
	    return -1;
	memcpy(&hdr, sec, sizeof(hdr));
	if (bcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
	    hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
	    hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) {
	    printf("Invalid GPT header\n");
	    return -1;
	}

	/* XXX: CRC check? */

	/*
	 * If the partition isn't specified, then search for the first UFS
	 * partition and hope it is /.  Perhaps we should be using an OS
	 * flag in the GPT entry to mark / partitions.
	 *
	 * If the partition is specified, then figure out the LBA for the
	 * sector containing that partition index and load it.
	 */
	entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
	if (dsk.part == -1) {
	    slba = hdr.hdr_lba_table;
	    elba = slba + hdr.hdr_entries / entries_per_sec;
	    while (slba < elba && dsk.part == -1) {
		if (drvread(sec, slba, 1))
		    return -1;
		for (part = 0; part < entries_per_sec; part++) {
		    ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz);
		    if (bcmp(&ent->ent_type, &freebsd_ufs_uuid,
			sizeof(uuid_t)) == 0) {
			dsk.part = (slba - hdr.hdr_lba_table) *
			    entries_per_sec + part + 1;
			dsk.start = ent->ent_lba_start;
			break;
		    }
		}
		slba++;
	    }
	    if (dsk.part == -1) {
		printf("No UFS partition was found\n");
		return -1;
	    }
	} else {
	    if (dsk.part > hdr.hdr_entries) {
		printf("Invalid partition index\n");
		return -1;
	    }
	    slba = hdr.hdr_lba_table + (dsk.part - 1) / entries_per_sec;
	    if (drvread(sec, slba, 1))
		return -1;
	    part = (dsk.part - 1) % entries_per_sec;
	    ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz);
	    if (bcmp(&ent->ent_type, &freebsd_ufs_uuid, sizeof(uuid_t)) != 0) {
		printf("Specified partition is not UFS\n");
		return -1;
	    }
	    dsk.start = ent->ent_lba_start;
	}
	/*
	 * XXX: No way to detect SCSI vs. ATA currently.
	 */
#if 0
	if (!dsk.init) {
	    if (d->d_type == DTYPE_SCSI)
		dsk.type = TYPE_DA;
	    dsk.init++;
	}
#endif
    }
    return drvread(buf, dsk.start + lba, nblk);
}
Beispiel #21
0
static int
tmpfs_rename(struct vop_rename_args *v)
{
	struct vnode *fdvp = v->a_fdvp;
	struct vnode *fvp = v->a_fvp;
	struct componentname *fcnp = v->a_fcnp;
	struct vnode *tdvp = v->a_tdvp;
	struct vnode *tvp = v->a_tvp;
	struct componentname *tcnp = v->a_tcnp;
	struct mount *mp = NULL;

	char *newname;
	int error;
	struct tmpfs_dirent *de;
	struct tmpfs_mount *tmp;
	struct tmpfs_node *fdnode;
	struct tmpfs_node *fnode;
	struct tmpfs_node *tnode;
	struct tmpfs_node *tdnode;

	MPASS(VOP_ISLOCKED(tdvp));
	MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp)));
	MPASS(fcnp->cn_flags & HASBUF);
	MPASS(tcnp->cn_flags & HASBUF);

	/* Disallow cross-device renames.
	 * XXX Why isn't this done by the caller? */
	if (fvp->v_mount != tdvp->v_mount ||
	    (tvp != NULL && fvp->v_mount != tvp->v_mount)) {
		error = EXDEV;
		goto out;
	}

	/* If source and target are the same file, there is nothing to do. */
	if (fvp == tvp) {
		error = 0;
		goto out;
	}

	/* If we need to move the directory between entries, lock the
	 * source so that we can safely operate on it. */
	if (fdvp != tdvp && fdvp != tvp) {
		if (vn_lock(fdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
			mp = tdvp->v_mount;
			error = vfs_busy(mp, 0);
			if (error != 0) {
				mp = NULL;
				goto out;
			}
			error = tmpfs_rename_relock(fdvp, &fvp, tdvp, &tvp,
			    fcnp, tcnp);
			if (error != 0) {
				vfs_unbusy(mp);
				return (error);
			}
			ASSERT_VOP_ELOCKED(fdvp,
			    "tmpfs_rename: fdvp not locked");
			ASSERT_VOP_ELOCKED(tdvp,
			    "tmpfs_rename: tdvp not locked");
			if (tvp != NULL)
				ASSERT_VOP_ELOCKED(tvp,
				    "tmpfs_rename: tvp not locked");
			if (fvp == tvp) {
				error = 0;
				goto out_locked;
			}
		}
	}

	tmp = VFS_TO_TMPFS(tdvp->v_mount);
	tdnode = VP_TO_TMPFS_DIR(tdvp);
	tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
	fdnode = VP_TO_TMPFS_DIR(fdvp);
	fnode = VP_TO_TMPFS_NODE(fvp);
	de = tmpfs_dir_lookup(fdnode, fnode, fcnp);

	/* Entry can disappear before we lock fdvp,
	 * also avoid manipulating '.' and '..' entries. */
	if (de == NULL) {
		if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
		    (fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
			error = EINVAL;
		else
			error = ENOENT;
		goto out_locked;
	}
	MPASS(de->td_node == fnode);

	/* If re-naming a directory to another preexisting directory
	 * ensure that the target directory is empty so that its
	 * removal causes no side effects.
	 * Kern_rename guarantees the destination to be a directory
	 * if the source is one. */
	if (tvp != NULL) {
		MPASS(tnode != NULL);

		if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
		    (tdnode->tn_flags & (APPEND | IMMUTABLE))) {
			error = EPERM;
			goto out_locked;
		}

		if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
			if (tnode->tn_size > 0) {
				error = ENOTEMPTY;
				goto out_locked;
			}
		} else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
			error = ENOTDIR;
			goto out_locked;
		} else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
			error = EISDIR;
			goto out_locked;
		} else {
			MPASS(fnode->tn_type != VDIR &&
				tnode->tn_type != VDIR);
		}
	}

	if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))
	    || (fdnode->tn_flags & (APPEND | IMMUTABLE))) {
		error = EPERM;
		goto out_locked;
	}

	/* Ensure that we have enough memory to hold the new name, if it
	 * has to be changed. */
	if (fcnp->cn_namelen != tcnp->cn_namelen ||
	    bcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) {
		newname = malloc(tcnp->cn_namelen, M_TMPFSNAME, M_WAITOK);
	} else
		newname = NULL;

	/* If the node is being moved to another directory, we have to do
	 * the move. */
	if (fdnode != tdnode) {
		/* In case we are moving a directory, we have to adjust its
		 * parent to point to the new parent. */
		if (de->td_node->tn_type == VDIR) {
			struct tmpfs_node *n;

			/* Ensure the target directory is not a child of the
			 * directory being moved.  Otherwise, we'd end up
			 * with stale nodes. */
			n = tdnode;
			/* TMPFS_LOCK garanties that no nodes are freed while
			 * traversing the list. Nodes can only be marked as
			 * removed: tn_parent == NULL. */
			TMPFS_LOCK(tmp);
			TMPFS_NODE_LOCK(n);
			while (n != n->tn_dir.tn_parent) {
				struct tmpfs_node *parent;

				if (n == fnode) {
					TMPFS_NODE_UNLOCK(n);
					TMPFS_UNLOCK(tmp);
					error = EINVAL;
					if (newname != NULL)
						    free(newname, M_TMPFSNAME);
					goto out_locked;
				}
				parent = n->tn_dir.tn_parent;
				TMPFS_NODE_UNLOCK(n);
				if (parent == NULL) {
					n = NULL;
					break;
				}
				TMPFS_NODE_LOCK(parent);
				if (parent->tn_dir.tn_parent == NULL) {
					TMPFS_NODE_UNLOCK(parent);
					n = NULL;
					break;
				}
				n = parent;
			}
			TMPFS_UNLOCK(tmp);
			if (n == NULL) {
				error = EINVAL;
				if (newname != NULL)
					    free(newname, M_TMPFSNAME);
				goto out_locked;
			}
			TMPFS_NODE_UNLOCK(n);

			/* Adjust the parent pointer. */
			TMPFS_VALIDATE_DIR(fnode);
			TMPFS_NODE_LOCK(de->td_node);
			de->td_node->tn_dir.tn_parent = tdnode;
			TMPFS_NODE_UNLOCK(de->td_node);

			/* As a result of changing the target of the '..'
			 * entry, the link count of the source and target
			 * directories has to be adjusted. */
			TMPFS_NODE_LOCK(tdnode);
			TMPFS_ASSERT_LOCKED(tdnode);
			tdnode->tn_links++;
			TMPFS_NODE_UNLOCK(tdnode);

			TMPFS_NODE_LOCK(fdnode);
			TMPFS_ASSERT_LOCKED(fdnode);
			fdnode->tn_links--;
			TMPFS_NODE_UNLOCK(fdnode);
		}
	}

	/* Do the move: just remove the entry from the source directory
	 * and insert it into the target one. */
	tmpfs_dir_detach(fdvp, de);

	if (fcnp->cn_flags & DOWHITEOUT)
		tmpfs_dir_whiteout_add(fdvp, fcnp);
	if (tcnp->cn_flags & ISWHITEOUT)
		tmpfs_dir_whiteout_remove(tdvp, tcnp);

	/* If the name has changed, we need to make it effective by changing
	 * it in the directory entry. */
	if (newname != NULL) {
		MPASS(tcnp->cn_namelen <= MAXNAMLEN);

		free(de->ud.td_name, M_TMPFSNAME);
		de->ud.td_name = newname;
		tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen);

		fnode->tn_status |= TMPFS_NODE_CHANGED;
		tdnode->tn_status |= TMPFS_NODE_MODIFIED;
	}

	/* If we are overwriting an entry, we have to remove the old one
	 * from the target directory. */
	if (tvp != NULL) {
		struct tmpfs_dirent *tde;

		/* Remove the old entry from the target directory. */
		tde = tmpfs_dir_lookup(tdnode, tnode, tcnp);
		tmpfs_dir_detach(tdvp, tde);

		/* Free the directory entry we just deleted.  Note that the
		 * node referred by it will not be removed until the vnode is
		 * really reclaimed. */
		tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde);
	}

	tmpfs_dir_attach(tdvp, de);

	cache_purge(fvp);
	if (tvp != NULL)
		cache_purge(tvp);
	cache_purge_negative(tdvp);

	error = 0;

out_locked:
	if (fdvp != tdvp && fdvp != tvp)
		VOP_UNLOCK(fdvp, 0);

out:
	/* Release target nodes. */
	/* XXX: I don't understand when tdvp can be the same as tvp, but
	 * other code takes care of this... */
	if (tdvp == tvp)
		vrele(tdvp);
	else
		vput(tdvp);
	if (tvp != NULL)
		vput(tvp);

	/* Release source nodes. */
	vrele(fdvp);
	vrele(fvp);

	if (mp != NULL)
		vfs_unbusy(mp);

	return error;
}
Beispiel #22
0
/*
 * Be sure a directory is empty except for "." and "..". Return 1 if empty,
 * return 0 if not empty or error.
 */
int
dosdirempty(struct denode *dep)
{
	int blsize;
	int error;
	u_long cn;
	daddr_t bn;
	struct buf *bp;
	struct msdosfsmount *pmp = dep->de_pmp;
	struct direntry *dentp;

	/*
	 * Since the filesize field in directory entries for a directory is
	 * zero, we just have to feel our way through the directory until
	 * we hit end of file.
	 */
	for (cn = 0;; cn++) {
		if ((error = pcbmap(dep, cn, &bn, NULL, &blsize)) != 0) {
			if (error == E2BIG)
				return (1);	/* it's empty */
			return (0);
		}
		error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), blsize, &bp);
		if (error) {
			brelse(bp);
			return (0);
		}
		for (dentp = (struct direntry *)bp->b_data;
		     (char *)dentp < bp->b_data + blsize;
		     dentp++) {
			if (dentp->deName[0] != SLOT_DELETED &&
			    (dentp->deAttributes & ATTR_VOLUME) == 0) {
				/*
				 * In dos directories an entry whose name
				 * starts with SLOT_EMPTY (0) starts the
				 * beginning of the unused part of the
				 * directory, so we can just return that it
				 * is empty.
				 */
				if (dentp->deName[0] == SLOT_EMPTY) {
					brelse(bp);
					return (1);
				}
				/*
				 * Any names other than "." and ".." in a
				 * directory mean it is not empty.
				 */
				if (bcmp(dentp->deName, ".          ", 11) &&
				    bcmp(dentp->deName, "..         ", 11)) {
					brelse(bp);
#ifdef MSDOSFS_DEBUG
					kprintf("dosdirempty(): entry found %02x, %02x\n",
					    dentp->deName[0], dentp->deName[1]);
#endif
					return (0);	/* not empty */
				}
			}
		}
		brelse(bp);
	}
	/* NOTREACHED */
}
Beispiel #23
0
int
ng_l2cap_l2ca_cfg_rsp_req(ng_l2cap_p l2cap, struct ng_mesg *msg)
{
	ng_l2cap_l2ca_cfg_rsp_ip	*ip = NULL;
	ng_l2cap_chan_p			 ch = NULL;
	ng_l2cap_cmd_p			 cmd = NULL;
	struct mbuf			*opt = NULL;
	u_int16_t			*mtu = NULL;
	ng_l2cap_flow_p			 flow = NULL;
	int				 error = 0;

	/* Check message */
	if (msg->header.arglen != sizeof(*ip)) {
		NG_L2CAP_ALERT(
"%s: %s - invalid L2CA_ConfigRsp request message size, size=%d\n",
			__func__, NG_NODE_NAME(l2cap->node),
			msg->header.arglen);
		error = EMSGSIZE;
		goto out;
	}

	ip = (ng_l2cap_l2ca_cfg_rsp_ip *)(msg->data);

	/* Check if we have this channel */
	ch = ng_l2cap_chan_by_scid(l2cap, ip->lcid,
				   NG_L2CAP_L2CA_IDTYPE_BREDR);
	if (ch == NULL) {
		NG_L2CAP_ERR(
"%s: %s - unexpected L2CA_ConfigRsp request message. " \
"Channel does not exist, lcid=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ip->lcid);
		error = ENOENT;
		goto out;
	}

	/* Check channel state */
	if (ch->state != NG_L2CAP_CONFIG) {
		NG_L2CAP_ERR(
"%s: %s - unexpected L2CA_ConfigRsp request message. " \
"Invalid channel state, state=%d, lcid=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), ch->state,
			ch->scid);
		error = EINVAL;
		goto out;
	}

	/* Set channel settings */
	if (ip->omtu != ch->omtu) {
		ch->omtu = ip->omtu;
		mtu = &ch->omtu;
	}

	if (bcmp(&ip->iflow, &ch->iflow, sizeof(ch->iflow)) != 0) { 
		bcopy(&ip->iflow, &ch->iflow, sizeof(ch->iflow));
		flow = &ch->iflow;
	}

	if (mtu != NULL || flow != NULL) {
		_ng_l2cap_build_cfg_options(opt, mtu, NULL, flow);
		if (opt == NULL) {
			error = ENOBUFS;
			goto out;
		}
	}

	/* Create L2CAP command */
	cmd = ng_l2cap_new_cmd(ch->con, ch, ch->ident, NG_L2CAP_CFG_RSP,
			msg->header.token);
	if (cmd == NULL) {
		NG_FREE_M(opt);
		error = ENOMEM;
		goto out;
	}

	_ng_l2cap_cfg_rsp(cmd->aux,cmd->ident,ch->dcid,0,NG_L2CAP_SUCCESS,opt);
	if (cmd->aux == NULL) {
		ng_l2cap_free_cmd(cmd);
		error = ENOBUFS;
		goto out;
	}

	/* XXX FIXME - not here ??? */
	ch->cfg_state |= NG_L2CAP_CFG_OUT;
	if (ch->cfg_state == NG_L2CAP_CFG_BOTH)
		ch->state = NG_L2CAP_OPEN;

	/* Link command to the queue */
	ng_l2cap_link_cmd(ch->con, cmd);
	ng_l2cap_lp_deliver(ch->con);
out:
	return (error);
} /* ng_l2cap_l2ca_cfg_rsp_req */
Beispiel #24
0
/*
 * Check to see if the directory described by target is in some
 * subdirectory of source.  This prevents something like the following from
 * succeeding and leaving a bunch or files and directories orphaned. mv
 * /a/b/c /a/b/c/d/e/f Where c and f are directories.
 *
 * source - the inode for /a/b/c
 * target - the inode for /a/b/c/d/e/f
 *
 * Returns 0 if target is NOT a subdirectory of source.
 * Otherwise returns a non-zero error number.
 * The target inode is always unlocked on return.
 */
int
doscheckpath(struct denode *source, struct denode *target)
{
	daddr_t scn;
	struct msdosfsmount *pmp;
	struct direntry *ep;
	struct denode *dep;
	struct buf *bp = NULL;
	int error = 0;

	dep = target;
	if ((target->de_Attributes & ATTR_DIRECTORY) == 0 ||
	    (source->de_Attributes & ATTR_DIRECTORY) == 0) {
		error = ENOTDIR;
		goto out;
	}
	if (dep->de_StartCluster == source->de_StartCluster) {
		error = EEXIST;
		goto out;
	}
	if (dep->de_StartCluster == MSDOSFSROOT)
		goto out;
	pmp = dep->de_pmp;
#ifdef	DIAGNOSTIC
	if (pmp != source->de_pmp)
		panic("doscheckpath: source and target on different filesystems");
#endif
	if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)
		goto out;

	for (;;) {
		if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) {
			error = ENOTDIR;
			break;
		}
		scn = dep->de_StartCluster;
		error = bread(pmp->pm_devvp, xcntodoff(pmp, scn),
			      pmp->pm_bpcluster, &bp);
		if (error)
			break;

		ep = (struct direntry *) bp->b_data + 1;
		if ((ep->deAttributes & ATTR_DIRECTORY) == 0 ||
		    bcmp(ep->deName, "..         ", 11) != 0) {
			error = ENOTDIR;
			break;
		}
		scn = getushort(ep->deStartCluster);
		if (FAT32(pmp))
			scn |= getushort(ep->deHighClust) << 16;

		if (scn == source->de_StartCluster) {
			error = EINVAL;
			break;
		}
		if (scn == MSDOSFSROOT)
			break;
		if (FAT32(pmp) && scn == pmp->pm_rootdirblk) {
			/*
			 * scn should be 0 in this case,
			 * but we silently ignore the error.
			 */
			break;
		}

		vput(DETOV(dep));
		brelse(bp);
		bp = NULL;
		/* NOTE: deget() clears dep on error */
		if ((error = deget(pmp, scn, 0, &dep)) != 0)
			break;
	}
out:;
	if (bp)
		brelse(bp);
	if (error == ENOTDIR)
		kprintf("doscheckpath(): .. not a directory?\n");
	if (dep != NULL)
		vput(DETOV(dep));
	return (error);
}
Beispiel #25
0
static void
dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh)
{
	int prec;
	struct pktq *q;
	uint count = 0;

	q = dhd_bus_txq(pub->bus);
	if (q == NULL)
		return;

	DHD_BTA(("dhd: flushing HCI ACL data for logical link %u...\n", llh));

	dhd_os_sdlock_txq(pub);

	/* Walk through the txq and toss all HCI ACL data packets */
	PKTQ_PREC_ITER(q, prec) {
		void *head_pkt = NULL;

		while (pktq_ppeek(q, prec) != head_pkt) {
			void *pkt = pktq_pdeq(q, prec);
			int ifidx;
			if(pkt == NULL)
			{
				DHD_BTA((" pktq_ppeek failed.\n"));
				return;
			}
			PKTPULL(pub->osh, pkt, dhd_bus_hdrlen(pub->bus));
			dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL);

			if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) {
				struct ether_header *eh =
				        (struct ether_header *)PKTDATA(pub->osh, pkt);

				if (ntoh16(eh->ether_type) < ETHER_TYPE_MIN) {
					struct dot11_llc_snap_header *lsh =
					        (struct dot11_llc_snap_header *)&eh[1];

					if (bcmp(lsh, BT_SIG_SNAP_MPROT,
					         DOT11_LLC_SNAP_HDR_LEN - 2) == 0 &&
					    ntoh16(lsh->type) == BTA_PROT_L2CAP) {
						amp_hci_ACL_data_t *ACL_data =
						        (amp_hci_ACL_data_t *)&lsh[1];
						uint16 handle = ltoh16(ACL_data->handle);

						if (HCI_ACL_DATA_HANDLE(handle) == llh) {
							PKTFREE(pub->osh, pkt, TRUE);
							count ++;
							continue;
						}
					}
				}
			}

			dhd_prot_hdrpush(pub, ifidx, pkt);
			PKTPUSH(pub->osh, pkt, dhd_bus_hdrlen(pub->bus));

			if (head_pkt == NULL)
				head_pkt = pkt;
			pktq_penq(q, prec, pkt);
		}
	}
Beispiel #26
0
/*
 * When we search a directory the blocks containing directory entries are
 * read and examined.  The directory entries contain information that would
 * normally be in the inode of a unix filesystem.  This means that some of
 * a directory's contents may also be in memory resident denodes (sort of
 * an inode).  This can cause problems if we are searching while some other
 * process is modifying a directory.  To prevent one process from accessing
 * incompletely modified directory information we depend upon being the
 * sole owner of a directory block.  bread/brelse provide this service.
 * This being the case, when a process modifies a directory it must first
 * acquire the disk block that contains the directory entry to be modified.
 * Then update the disk block and the denode, and then write the disk block
 * out to disk.  This way disk blocks containing directory entries and in
 * memory denode's will be in synch.
 *
 * msdosfs_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
 *		  struct componentname *a_cnp)
 */
int
msdosfs_lookup(struct vop_old_lookup_args *ap)
{
	struct mbnambuf nb;
	struct vnode *vdp = ap->a_dvp;
	struct vnode **vpp = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	daddr_t bn;
	int error;
	int lockparent;
	int wantparent;
	int slotcount;
	int slotoffset = 0;
	int frcn;
	u_long cluster;
	int blkoff;
	int diroff;
	int blsize;
	int isadir;		/* ~0 if found direntry is a directory	 */
	u_long scn;		/* starting cluster number		 */
	struct vnode *pdp;
	struct denode *dp;
	struct denode *tdp;
	struct msdosfsmount *pmp;
	struct buf *bp = NULL;
	struct direntry *dep = NULL;
	u_char dosfilename[12];
	int flags = cnp->cn_flags;
	int nameiop = cnp->cn_nameiop;
	int unlen;

	int wincnt = 1;
	int chksum = -1;
	int olddos = 1;
	cnp->cn_flags &= ~CNP_PDIRUNLOCK;

#ifdef MSDOSFS_DEBUG
	kprintf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr);
#endif
	dp = VTODE(vdp);
	pmp = dp->de_pmp;
	*vpp = NULL;
	lockparent = flags & CNP_LOCKPARENT;
	wantparent = flags & (CNP_LOCKPARENT | CNP_WANTPARENT);
#ifdef MSDOSFS_DEBUG
	kprintf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n",
	    vdp, dp, dp->de_Attributes);
#endif

	/*
	 * If they are going after the . or .. entry in the root directory,
	 * they won't find it.  DOS filesystems don't have them in the root
	 * directory.  So, we fake it. deget() is in on this scam too.
	 */
	if ((vdp->v_flag & VROOT) && cnp->cn_nameptr[0] == '.' &&
	    (cnp->cn_namelen == 1 ||
		(cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) {
		isadir = ATTR_DIRECTORY;
		scn = MSDOSFSROOT;
#ifdef MSDOSFS_DEBUG
		kprintf("msdosfs_lookup(): looking for . or .. in root directory\n");
#endif
		cluster = MSDOSFSROOT;
		blkoff = MSDOSFSROOT_OFS;
		goto foundroot;
	}
	switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename,
	    cnp->cn_namelen, 0, pmp)) {
	case 0:
		return (EINVAL);
	case 1:
		break;
	case 2:
		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
		    cnp->cn_namelen, pmp) + 1;
		break;
	case 3:
		olddos = 0;
		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
		    cnp->cn_namelen, pmp) + 1;
		break;
	}
	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) {
		wincnt = 1;
		olddos = 1;
	}
	unlen = winLenFixup(cnp->cn_nameptr, cnp->cn_namelen);

	/*
	 * Suppress search for slots unless creating
	 * file and at end of pathname, in which case
	 * we watch for a place to put the new file in
	 * case it doesn't already exist.
	 */
	slotcount = wincnt;
	if (nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME)
		slotcount = 0;

#ifdef MSDOSFS_DEBUG
	kprintf("msdosfs_lookup(): dos version of filename %s, length %ld\n",
	    dosfilename, cnp->cn_namelen);
#endif
	/*
	 * Search the directory pointed at by vdp for the name pointed at
	 * by cnp->cn_nameptr.
	 */
	tdp = NULL;
	mbnambuf_init(&nb);
	/*
	 * The outer loop ranges over the clusters that make up the
	 * directory.  Note that the root directory is different from all
	 * other directories.  It has a fixed number of blocks that are not
	 * part of the pool of allocatable clusters.  So, we treat it a
	 * little differently. The root directory starts at "cluster" 0.
	 */
	diroff = 0;
	for (frcn = 0;; frcn++) {
		error = pcbmap(dp, frcn, &bn, &cluster, &blsize);
		if (error) {
			if (error == E2BIG)
				break;
			return (error);
		}
		error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), blsize, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}
		for (blkoff = 0; blkoff < blsize;
		     blkoff += sizeof(struct direntry),
		     diroff += sizeof(struct direntry)) {
			dep = (struct direntry *)(bp->b_data + blkoff);
			/*
			 * If the slot is empty and we are still looking
			 * for an empty then remember this one.  If the
			 * slot is not empty then check to see if it
			 * matches what we are looking for.  If the slot
			 * has never been filled with anything, then the
			 * remainder of the directory has never been used,
			 * so there is no point in searching it.
			 */
			if (dep->deName[0] == SLOT_EMPTY ||
			    dep->deName[0] == SLOT_DELETED) {
				/*
				 * Drop memory of previous long matches
				 */
				chksum = -1;
				mbnambuf_init(&nb);

				if (slotcount < wincnt) {
					slotcount++;
					slotoffset = diroff;
				}
				if (dep->deName[0] == SLOT_EMPTY) {
					brelse(bp);
					goto notfound;
				}
			} else {
				/*
				 * If there wasn't enough space for our winentries,
				 * forget about the empty space
				 */
				if (slotcount < wincnt)
					slotcount = 0;

				/*
				 * Check for Win95 long filename entry
				 */
				if (dep->deAttributes == ATTR_WIN95) {
				if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
						continue;
					chksum = win2unixfn(&nb,
                                            (struct winentry *)dep, chksum,
                                            pmp);
					continue;
				}

                                chksum = winChkName(&nb,
                                    (const u_char *)cnp->cn_nameptr, unlen,
                                    chksum, pmp);
				if (chksum == -2) {
                                        chksum = -1;
                                        continue;
                                }

				/*
				 * Ignore volume labels (anywhere, not just
				 * the root directory).
				 */
				if (dep->deAttributes & ATTR_VOLUME) {
					chksum = -1;
					continue;
				}

				/*
				 * Check for a checksum or name match
				 */
				if (chksum != winChksum(dep->deName)
				    && (!olddos || bcmp(dosfilename, dep->deName, 11))) {
					chksum = -1;
					continue;
				}
#ifdef MSDOSFS_DEBUG
				kprintf("msdosfs_lookup(): match blkoff %d, diroff %d\n",
				    blkoff, diroff);
#endif
				/*
				 * Remember where this directory
				 * entry came from for whoever did
				 * this lookup.
				 */
				dp->de_fndoffset = diroff;
				dp->de_fndcnt = wincnt - 1;

				goto found;
			}
		}	/* for (blkoff = 0; .... */
		/*
		 * Release the buffer holding the directory cluster just
		 * searched.
		 */
		brelse(bp);
	}	/* for (frcn = 0; ; frcn++) */

notfound:
	/*
	 * We hold no disk buffers at this point.
	 */

	/*
	 * Fixup the slot description to point to the place where
	 * we might put the new DOS direntry (putting the Win95
	 * long name entries before that)
	 */
	if (!slotcount) {
		slotcount = 1;
		slotoffset = diroff;
	}
	if (wincnt > slotcount)
		slotoffset += sizeof(struct direntry) * (wincnt - slotcount);

	/*
	 * If we get here we didn't find the entry we were looking for. But
	 * that's ok if we are creating or renaming and are at the end of
	 * the pathname and the directory hasn't been removed.
	 */
#ifdef MSDOSFS_DEBUG
	kprintf("msdosfs_lookup(): op %d, refcnt %ld\n",
	    nameiop, dp->de_refcnt);
	kprintf("               slotcount %d, slotoffset %d\n",
	       slotcount, slotoffset);
#endif
	if ((nameiop == NAMEI_CREATE || nameiop == NAMEI_RENAME) &&
	    dp->de_refcnt > 0) {
		/*
		 * Access for write is interpreted as allowing
		 * creation of files in the directory.
		 */
		error = VOP_EACCESS(vdp, VWRITE, cnp->cn_cred);
		if (error)
			return (error);
		/*
		 * Return an indication of where the new directory
		 * entry should be put.
		 */
		dp->de_fndoffset = slotoffset;
		dp->de_fndcnt = wincnt - 1;

		/*
		 * We return with the directory locked, so that
		 * the parameters we set up above will still be
		 * valid if we actually decide to do a direnter().
		 * We return ni_vp == NULL to indicate that the entry
		 * does not currently exist; we leave a pointer to
		 * the (locked) directory inode in ndp->ni_dvp.
		 * The pathname buffer is saved so that the name
		 * can be obtained later.
		 *
		 * NB - if the directory is unlocked, then this
		 * information cannot be used.
		 */
		if (!lockparent) {
			vn_unlock(vdp);
			cnp->cn_flags |= CNP_PDIRUNLOCK;
		}
		return (EJUSTRETURN);
	}
	return (ENOENT);

found:
	/*
	 * NOTE:  We still have the buffer with matched directory entry at
	 * this point.
	 */
	isadir = dep->deAttributes & ATTR_DIRECTORY;
	scn = getushort(dep->deStartCluster);
	if (FAT32(pmp)) {
		scn |= getushort(dep->deHighClust) << 16;
		if (scn == pmp->pm_rootdirblk) {
			/*
			 * There should actually be 0 here.
			 * Just ignore the error.
			 */
			scn = MSDOSFSROOT;
		}
	}

	if (isadir) {
		cluster = scn;
		if (cluster == MSDOSFSROOT)
			blkoff = MSDOSFSROOT_OFS;
		else
			blkoff = 0;
	} else if (cluster == MSDOSFSROOT)
		blkoff = diroff;

	/*
	 * Now release buf to allow deget to read the entry again.
	 * Reserving it here and giving it to deget could result
	 * in a deadlock.
	 */
	brelse(bp);
	bp = NULL;
	
foundroot:
	/*
	 * If we entered at foundroot, then we are looking for the . or ..
	 * entry of the filesystems root directory.  isadir and scn were
	 * setup before jumping here.  And, bp is already null.
	 */
	if (FAT32(pmp) && scn == MSDOSFSROOT)
		scn = pmp->pm_rootdirblk;

	/*
	 * If deleting, and at end of pathname, return
	 * parameters which can be used to remove file.
	 * If the wantparent flag isn't set, we return only
	 * the directory (in ndp->ni_dvp), otherwise we go
	 * on and lock the inode, being careful with ".".
	 */
	if (nameiop == NAMEI_DELETE) {
		/*
		 * Don't allow deleting the root.
		 */
		if (blkoff == MSDOSFSROOT_OFS)
			return EROFS;				/* really? XXX */

		/*
		 * Write access to directory required to delete files.
		 */
		error = VOP_EACCESS(vdp, VWRITE, cnp->cn_cred);
		if (error)
			return (error);

		/*
		 * Return pointer to current entry in dp->i_offset.
		 * Save directory inode pointer in ndp->ni_dvp for dirremove().
		 */
		if (dp->de_StartCluster == scn && isadir) {	/* "." */
			vref(vdp);
			*vpp = vdp;
			return (0);
		}
		error = deget(pmp, cluster, blkoff, &tdp);
		if (error)
			return (error);
		*vpp = DETOV(tdp);
		if (!lockparent) {
			vn_unlock(vdp);
			cnp->cn_flags |= CNP_PDIRUNLOCK;
		}
		return (0);
	}

	/*
	 * If rewriting (RENAME), return the inode and the
	 * information required to rewrite the present directory
	 * Must get inode of directory entry to verify it's a
	 * regular file, or empty directory.
	 */
	if (nameiop == NAMEI_RENAME && wantparent) {
		if (blkoff == MSDOSFSROOT_OFS)
			return EROFS;			/* really? XXX */

		error = VOP_EACCESS(vdp, VWRITE, cnp->cn_cred);
		if (error)
			return (error);

		/*
		 * Careful about locking second inode.
		 * This can only occur if the target is ".".
		 */
		if (dp->de_StartCluster == scn && isadir)
			return (EISDIR);

		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
			return (error);
		*vpp = DETOV(tdp);
		if (!lockparent) {
			vn_unlock(vdp);
			cnp->cn_flags |= CNP_PDIRUNLOCK;
		}
		return (0);
	}

	/*
	 * Step through the translation in the name.  We do not `vput' the
	 * directory because we may need it again if a symbolic link
	 * is relative to the current directory.  Instead we save it
	 * unlocked as "pdp".  We must get the target inode before unlocking
	 * the directory to insure that the inode will not be removed
	 * before we get it.  We prevent deadlock by always fetching
	 * inodes from the root, moving down the directory tree. Thus
	 * when following backward pointers ".." we must unlock the
	 * parent directory before getting the requested directory.
	 * There is a potential race condition here if both the current
	 * and parent directories are removed before the VFS_VGET for the
	 * inode associated with ".." returns.  We hope that this occurs
	 * infrequently since we cannot avoid this race condition without
	 * implementing a sophisticated deadlock detection algorithm.
	 * Note also that this simple deadlock detection scheme will not
	 * work if the file system has any hard links other than ".."
	 * that point backwards in the directory structure.
	 */
	pdp = vdp;
	if (flags & CNP_ISDOTDOT) {
		vn_unlock(pdp);
		cnp->cn_flags |= CNP_PDIRUNLOCK;
		error = deget(pmp, cluster, blkoff,  &tdp);
		if (error) {
			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); 
			cnp->cn_flags &= ~CNP_PDIRUNLOCK;
			return (error);
		}
		if (lockparent) {
			error = vn_lock(pdp, LK_EXCLUSIVE | LK_FAILRECLAIM);
			if (error) {
				vput(DETOV(tdp));
				return (error);
			}
			cnp->cn_flags &= ~CNP_PDIRUNLOCK;
		}
		*vpp = DETOV(tdp);
	} else if (dp->de_StartCluster == scn && isadir) {
		vref(vdp);	/* we want ourself, ie "." */
		*vpp = vdp;
	} else {
		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
			return (error);
		if (!lockparent) {
			vn_unlock(pdp);
			cnp->cn_flags |= CNP_PDIRUNLOCK;
		}
		*vpp = DETOV(tdp);
	}
	return (0);
}
static int
cd9660_findfile(int disk, const char *path, int *startp, int *lenp)
{
	void *buf;
	struct iso_primary_descriptor *vd;
	size_t buf_size, read, dsize, off;
	daddr_t bno, boff;
	struct iso_directory_record rec;
	struct iso_directory_record *dp = 0;
	int rc = 0;
	
	/* First find the volume descriptor */
	buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);
	vd = buf;
	for (bno = 16;; bno++) {
		read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno));
		if (read != ISO_DEFAULT_BLOCK_SIZE) {
			rc = EIO;
			goto out;
		}
		rc = EINVAL;
		if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_END)
			goto out;
		if (isonum_711(vd->type) == ISO_VD_PRIMARY)
			break;
	}
	if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) {
		rc = EINVAL;
		goto out;
	}
	
	rec = *(struct iso_directory_record *) vd->root_directory_record;
	if (*path == '/') path++; /* eat leading '/' */

	while (*path) {
		bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
		dsize = isonum_733(rec.size);
		off = 0;
		boff = 0;

		while (off < dsize) {
			if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) {
				read = pread(disk, buf,
					     ISO_DEFAULT_BLOCK_SIZE,
					     cdb2off(bno + boff));
				if (read != ISO_DEFAULT_BLOCK_SIZE) {
					rc = EIO;
					goto out;
				}
				boff++;
				dp = (struct iso_directory_record *) buf;
			}
			if (isonum_711(dp->length) == 0) {
			    /* skip to next block, if any */
			    off = boff * ISO_DEFAULT_BLOCK_SIZE;
			    continue;
			}

			if (dirmatch(path, dp))
				break;

			dp = (struct iso_directory_record *)
				((char *) dp + isonum_711(dp->length));
			off += isonum_711(dp->length);
		}
		if (off == dsize) {
			rc = ENOENT;
			goto out;
		}

		rec = *dp;
		while (*path && *path != '/') /* look for next component */
			path++;
		if (*path) path++; /* skip '/' */
	}

	*startp = cdb2off(isonum_733(rec.extent)
			  + isonum_711(rec.ext_attr_length));
	*lenp = isonum_733(rec.size);
	rc = 0;

 out:
	free(buf);
	return rc;
}
Beispiel #28
0
/*
 * Create a unique DOS name in dvp
 */
int
uniqdosname(struct denode *dep, struct componentname *cnp, u_char *cp)
{
	struct msdosfsmount *pmp = dep->de_pmp;
	struct direntry *dentp;
	int gen;
	int blsize;
	u_long cn;
	daddr_t bn;
	struct buf *bp;
	int error;
	
	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
		return (unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
		    cnp->cn_namelen, 0, pmp) ?
		    0 : EINVAL);

	for (gen = 1;; gen++) {
		/*
		 * Generate DOS name with generation number
		 */
		if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
		    cnp->cn_namelen, gen, pmp))
			return gen == 1 ? EINVAL : EEXIST;

		/*
		 * Now look for a dir entry with this exact name
		 */
		for (cn = error = 0; !error; cn++) {
			if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) {
				if (error == E2BIG)	/* EOF reached and not found */
					return 0;
				return error;
			}
			error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), blsize, &bp);
			if (error) {
				brelse(bp);
				return error;
			}
			for (dentp = (struct direntry *)bp->b_data;
			     (char *)dentp < bp->b_data + blsize;
			     dentp++) {
				if (dentp->deName[0] == SLOT_EMPTY) {
					/*
					 * Last used entry and not found
					 */
					brelse(bp);
					return 0;
				}
				/*
				 * Ignore volume labels and Win95 entries
				 */
				if (dentp->deAttributes & ATTR_VOLUME)
					continue;
				if (!bcmp(dentp->deName, cp, 11)) {
					error = EEXIST;
					break;
				}
			}
			brelse(bp);
		}
	}
}
/*
 * Ethernet output routine.
 * Encapsulate a packet of type family for the local net.
 * Assumes that ifp is actually pointer to ethercom structure.
 */
int
ssh_interceptor_ether_output(struct ifnet *ifp, struct mbuf *m0,
                             struct sockaddr *dst, struct rtentry *rt0)
{
        u_int16_t etype = 0;
        int s, error = 0, hdrcmplt = 0;
        u_char esrc[6], edst[6];
        struct mbuf *m = m0;
        struct rtentry *rt;
        struct mbuf *mcopy = (struct mbuf *)0;
        struct ether_header *eh, ehd;
#ifdef INET
        struct arphdr *ah;
#endif /* INET */
#ifdef NETATALK
        struct at_ifaddr *aa;
#endif /* NETATALK */

        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
                senderr(ENETDOWN);
        ifp->if_lastchange = time;
        if ((rt = rt0) != NULL) {
                if ((rt->rt_flags & RTF_UP) == 0) {
                        if ((rt0 = rt = rtalloc1(dst, 1)) != NULL) {
                                rt->rt_refcnt--;
                                if (rt->rt_ifp != ifp)
                                        return (*rt->rt_ifp->if_output)
                                                        (ifp, m0, dst, rt);
                        } else
                                senderr(EHOSTUNREACH);
                }
                if ((rt->rt_flags & RTF_GATEWAY) && dst->sa_family != AF_NS) {
                        if (rt->rt_gwroute == 0)
                                goto lookup;
                        if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
                                rtfree(rt); rt = rt0;
                        lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
                                if ((rt = rt->rt_gwroute) == 0)
                                        senderr(EHOSTUNREACH);
                                /* the "G" test below also prevents rt == rt0 */
                                if ((rt->rt_flags & RTF_GATEWAY) ||
                                    (rt->rt_ifp != ifp)) {
                                        rt->rt_refcnt--;
                                        rt0->rt_gwroute = 0;
                                        senderr(EHOSTUNREACH);
                                }
                        }
                }
                if (rt->rt_flags & RTF_REJECT)
                        if (rt->rt_rmx.rmx_expire == 0 ||
                            time.tv_sec < rt->rt_rmx.rmx_expire)
                                senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
        }
        switch (dst->sa_family) {

#ifdef INET
        case AF_INET:
                if (m->m_flags & M_BCAST)
                        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
                                sizeof(edst));

                else if (m->m_flags & M_MCAST) {
                        ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr,
                            (caddr_t)edst)

                } else if (!arpresolve(ifp, rt, m, dst, edst))
                        return (0);     /* if not yet resolved */
                /* If broadcasting on a simplex interface, loopback a copy */
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
                etype = htons(ETHERTYPE_IP);
                break;

        case AF_ARP:
                ah = mtod(m, struct arphdr *);
                if (m->m_flags & M_BCAST)
                        bcopy((caddr_t)etherbroadcastaddr, (caddr_t)edst,
                                sizeof(edst));
                else
                        bcopy((caddr_t)ar_tha(ah),
                                (caddr_t)edst, sizeof(edst));

                ah->ar_hrd = htons(ARPHRD_ETHER);

                switch(ntohs(ah->ar_op)) {
                case ARPOP_REVREQUEST:
                case ARPOP_REVREPLY:
                        etype = htons(ETHERTYPE_REVARP);
                        break;

                case ARPOP_REQUEST:
                case ARPOP_REPLY:
                default:
                        etype = htons(ETHERTYPE_ARP);
                }

                break;
#endif
#ifdef INET6
        case AF_INET6:
#ifdef OLDIP6OUTPUT
                if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst))
                        return(0);      /* if not yet resolves */
#else
                if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst)){
                        /* this must be impossible, so we bark */
                        printf("nd6_storelladdr failed\n");
                        return(0);
                }
#endif /* OLDIP6OUTPUT */
                etype = htons(ETHERTYPE_IPV6);
                break;
#endif
#ifdef NETATALK
    case AF_APPLETALK:
                if (!aarpresolve(ifp, m, (struct sockaddr_at *)dst, edst)) {
#ifdef NETATALKDEBUG
                        printf("aarpresolv failed\n");
#endif /* NETATALKDEBUG */
                        return (0);
                }
                /*
                 * ifaddr is the first thing in at_ifaddr
                 */
                aa = (struct at_ifaddr *) at_ifawithnet(
                    (struct sockaddr_at *)dst, ifp);
                if (aa == NULL)
                    goto bad;

                /*
                 * In the phase 2 case, we need to prepend an mbuf for the
                 * llc header.  Since we must preserve the value of m,
                 * which is passed to us by value, we m_copy() the first
                 * mbuf, and use it for our llc header.
                 */
                if (aa->aa_flags & AFA_PHASE2) {
                        struct llc llc;

                        M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
                        llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
                        llc.llc_control = LLC_UI;
                        bcopy(at_org_code, llc.llc_snap_org_code,
                            sizeof(llc.llc_snap_org_code));
                        llc.llc_snap_ether_type = htons(ETHERTYPE_ATALK);
                        bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
                } else {
                        etype = htons(ETHERTYPE_ATALK);
                }
                break;
#endif /* NETATALK */
#ifdef NS
        case AF_NS:
                etype = htons(ETHERTYPE_NS);
                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
                    (caddr_t)edst, sizeof (edst));
                if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
                        return (looutput(ifp, m, dst, rt));
                /* If broadcasting on a simplex interface, loopback a copy */
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
                break;
#endif
#ifdef IPX
        case AF_IPX:
                etype = htons(ETHERTYPE_IPX);
                bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
                    (caddr_t)edst, sizeof (edst));
                /* If broadcasting on a simplex interface, loopback a copy */
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
                        mcopy = m_copy(m, 0, (int)M_COPYALL);
                break;
#endif
#ifdef  ISO
        case AF_ISO: {
                int     snpalen;
                struct  llc *l;
                struct sockaddr_dl *sdl;

                if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
                    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
                        bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
                } else {
                        error = iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
                                                (char *)edst, &snpalen);
                        if (error)
                                goto bad; /* Not Resolved */
                }
                /* If broadcasting on a simplex interface, loopback a copy */
                if (*edst & 1)
                        m->m_flags |= (M_BCAST|M_MCAST);
                if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
                        if (mcopy) {
                                eh = mtod(mcopy, struct ether_header *);
                                bcopy((caddr_t)edst,
                                      (caddr_t)eh->ether_dhost, sizeof (edst));
                                bcopy(LLADDR(ifp->if_sadl),
                                      (caddr_t)eh->ether_shost, sizeof (edst));
                        }
                }
                M_PREPEND(m, 3, M_DONTWAIT);
                if (m == NULL)
                        return (0);
                l = mtod(m, struct llc *);
                l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
                l->llc_control = LLC_UI;
#ifdef ARGO_DEBUG
                if (argo_debug[D_ETHER]) {
                        int i;
                        printf("unoutput: sending pkt to: ");
                        for (i=0; i<6; i++)
                                printf("%x ", edst[i] & 0xff);
                        printf("\n");
                }
#endif
                } break;
#endif /* ISO */
#ifdef  LLC
/*      case AF_NSAP: */
        case AF_CCITT: {
                struct sockaddr_dl *sdl =
                        (struct sockaddr_dl *) rt -> rt_gateway;

                if (sdl && sdl->sdl_family == AF_LINK
                    && sdl->sdl_alen > 0) {
                        bcopy(LLADDR(sdl), (char *)edst,
                                sizeof(edst));
                } else goto bad; /* Not a link interface ? Funny ... */
                if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
                    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
                        M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
                        if (mcopy) {
                                eh = mtod(mcopy, struct ether_header *);
                                bcopy((caddr_t)edst,
                                      (caddr_t)eh->ether_dhost, sizeof (edst));
                                bcopy(LLADDR(ifp->if_sadl),
                                      (caddr_t)eh->ether_shost, sizeof (edst));
                        }
                }
#ifdef LLC_DEBUG
                {
                        int i;
                        struct llc *l = mtod(m, struct llc *);

                        printf("ether_output: sending LLC2 pkt to: ");
                        for (i=0; i<6; i++)
                                printf("%x ", edst[i] & 0xff);
                        printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
                            m->m_pkthdr.len, l->llc_dsap & 0xff, l->llc_ssap &0xff,
                            l->llc_control & 0xff);

                }
#endif /* LLC_DEBUG */
                } break;
Beispiel #30
0
int
ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
    struct ifnet **ifp, struct secpolicy **sp)
{
#ifdef IPSEC
	struct tdb_ident *tdbi;
	struct m_tag *mtag;
	/* XXX int s; */
	if (sp == NULL)
		return 1;
	mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
	if (mtag != NULL) {
		tdbi = (struct tdb_ident *)(mtag + 1);
		*sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
		if (*sp == NULL)
			*error = -EINVAL;	/* force silent drop */
		m_tag_delete(*m, mtag);
	} else {
		*sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
					error, inp);
	}

	/*
	 * There are four return cases:
	 *    sp != NULL		    apply IPsec policy
	 *    sp == NULL, error == 0	    no IPsec handling needed
	 *    sp == NULL, error == -EINVAL  discard packet w/o error
	 *    sp == NULL, error != 0	    discard packet, report error
	 */
	if (*sp != NULL) {
		/* Loop detection, check if ipsec processing already done */
		KASSERT((*sp)->req != NULL, ("ip_output: no ipsec request"));
		for (mtag = m_tag_first(*m); mtag != NULL;
		     mtag = m_tag_next(*m, mtag)) {
			if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
				continue;
			if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
			    mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
				continue;
			/*
			 * Check if policy has an SA associated with it.
			 * This can happen when an SP has yet to acquire
			 * an SA; e.g. on first reference.  If it occurs,
			 * then we let ipsec4_process_packet do its thing.
			 */
			if ((*sp)->req->sav == NULL)
				break;
			tdbi = (struct tdb_ident *)(mtag + 1);
			if (tdbi->spi == (*sp)->req->sav->spi &&
			    tdbi->proto == (*sp)->req->sav->sah->saidx.proto &&
			    bcmp(&tdbi->dst, &(*sp)->req->sav->sah->saidx.dst,
				 sizeof (union sockaddr_union)) == 0) {
				/*
				 * No IPsec processing is needed, free
				 * reference to SP.
				 *
				 * NB: null pointer to avoid free at
				 *     done: below.
				 */
				KEY_FREESP(sp), *sp = NULL;
				/* XXX splx(s); */
				goto done;
			}
		}

		/*
		 * Do delayed checksums now because we send before
		 * this is done in the normal processing path.
		 */
		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
			ipseclog((LOG_DEBUG,
			    "%s: we do not support IPv4 over IPv6", __func__));
#ifdef INET
			in_delayed_cksum(*m);
#endif
			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
		}

		/*
		 * Preserve KAME behaviour: ENOENT can be returned
		 * when an SA acquire is in progress.  Don't propagate
		 * this to user-level; it confuses applications.
		 *
		 * XXX this will go away when the SADB is redone.
		 */
		if (*error == ENOENT)
			*error = 0;
		goto do_ipsec;
	} else {	/* sp == NULL */
		if (*error != 0) {
			/*
			 * Hack: -EINVAL is used to signal that a packet
			 * should be silently discarded.  This is typically
			 * because we asked key management for an SA and
			 * it was delayed (e.g. kicked up to IKE).
			 */
			if (*error == -EINVAL)
				*error = 0;
			goto bad;
		} else {
			/* No IPsec processing for this packet. */
		}
	}
done:
	return 0;
do_ipsec:
	return -1;
bad:
	return 1;
#endif /* IPSEC */
	return 0;
}